From f2cb3cf86e4217581443d93e863c891a05066e60 Mon Sep 17 00:00:00 2001 From: "phajdan.jr@chromium.org" Date: Thu, 21 Mar 2013 01:40:53 +0000 Subject: net: move host_resolver files from net/base to net/dns BUG=70818 Review URL: https://codereview.chromium.org/12518036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@189485 0039d316-1c4b-4281-b951-d872f2087c98 --- .../chrome_net_benchmarking_message_filter.cc | 2 +- .../app_mode/kiosk_app_manager_browsertest.cc | 2 +- .../extensions/wallpaper_private_apitest.cc | 2 +- .../browser/extensions/activity_log_browsertest.cc | 2 +- .../cloud_print_private_apitest.cc | 2 +- chrome/browser/extensions/api/dns/dns_api.h | 2 +- chrome/browser/extensions/api/dns/dns_apitest.cc | 2 +- .../extensions/api/dns/host_resolver_wrapper.h | 2 +- .../api/dns/mock_host_resolver_creator.cc | 2 +- .../api/extension_action/script_badge_apitest.cc | 2 +- .../extensions/api/history/history_apitest.cc | 2 +- chrome/browser/extensions/api/idle/idle_apitest.cc | 2 +- .../api/page_capture/page_capture_apitest.cc | 4 +- .../api/permissions/permissions_apitest.cc | 2 +- .../push_messaging/push_messaging_canary_test.cc | 2 +- .../api/push_messaging/sync_setup_helper.h | 2 +- chrome/browser/extensions/api/socket/socket_api.h | 2 +- .../extensions/api/socket/socket_apitest.cc | 2 +- .../api/web_navigation/web_navigation_apitest.cc | 4 +- .../api/web_request/web_request_api_unittest.cc | 2 +- .../api/web_request/web_request_apitest.cc | 2 +- .../web_socket_proxy_private_api.cc | 2 +- .../webstore_private/webstore_private_apitest.cc | 2 +- .../extensions/app_background_page_apitest.cc | 2 +- chrome/browser/extensions/app_process_apitest.cc | 2 +- .../extensions/chrome_app_api_browsertest.cc | 2 +- .../browser/extensions/content_script_apitest.cc | 2 +- .../extensions/content_security_policy_apitest.cc | 2 +- .../browser/extensions/cross_origin_xhr_apitest.cc | 2 +- .../browser/extensions/execute_script_apitest.cc | 2 +- .../extension_context_menu_browsertest.cc | 2 +- .../extensions/extension_dom_clipboard_apitest.cc | 2 +- .../extensions/extension_icon_source_apitest.cc | 2 +- .../extensions/extension_incognito_apitest.cc | 2 +- .../extensions/extension_javascript_url_apitest.cc | 2 +- .../extensions/extension_nacl_browsertest.cc | 2 +- .../extension_resource_request_policy_apitest.cc | 2 +- .../browser/extensions/extension_tabs_apitest.cc | 2 +- .../extensions/extension_websocket_apitest.cc | 2 +- .../browser/extensions/isolated_app_browsertest.cc | 2 +- .../extensions/lazy_background_page_apitest.cc | 2 +- .../extensions/process_management_browsertest.cc | 2 +- .../webstore_startup_installer_browsertest.cc | 2 +- chrome/browser/extensions/window_open_apitest.cc | 2 +- chrome/browser/intranet_redirect_detector.h | 2 +- chrome/browser/io_thread.cc | 4 +- chrome/browser/net/connection_tester.cc | 2 +- chrome/browser/net/connection_tester_unittest.cc | 2 +- chrome/browser/net/cookie_policy_browsertest.cc | 2 +- chrome/browser/net/network_stats.h | 2 +- chrome/browser/net/network_stats_unittest.cc | 4 +- chrome/browser/net/predictor.cc | 4 +- chrome/browser/net/predictor_browsertest.cc | 4 +- chrome/browser/net/predictor_unittest.cc | 2 +- .../policy/cloud/device_management_service.cc | 2 +- chrome/browser/prerender/prerender_browsertest.cc | 2 +- chrome/browser/rlz/rlz_extension_apitest.cc | 4 +- chrome/browser/safe_browsing/safe_browsing_test.cc | 2 +- .../template_url_scraper_unittest.cc | 4 +- chrome/browser/sync/test/integration/sync_test.h | 2 +- .../task_manager/task_manager_browsertest.cc | 2 +- chrome/browser/ui/browser_browsertest.cc | 2 +- .../browser/ui/login/login_prompt_browsertest.cc | 2 +- .../browser/ui/omnibox/omnibox_view_browsertest.cc | 2 +- .../search/instant_extended_manual_browsertest.cc | 2 +- .../ui/webui/net_internals/net_internals_ui.cc | 2 +- .../net_internals/net_internals_ui_browsertest.cc | 4 +- chrome/common/extensions/extension_unittest.cc | 2 +- chrome/service/net/service_url_request_context.cc | 2 +- chrome/service/net/service_url_request_context.h | 2 +- chrome/test/base/chrome_test_suite.cc | 2 +- chrome/test/base/in_process_browser_test.cc | 2 +- chrome/test/perf/rendering/throughput_tests.cc | 2 +- chrome_frame/test/test_server_test.cc | 2 +- .../renderer_host/p2p/socket_dispatcher_host.cc | 4 +- .../pepper_host_resolver_private_message_filter.cc | 2 +- .../renderer_host/pepper/pepper_lookup_request.h | 4 +- .../renderer_host/pepper/pepper_tcp_socket.cc | 4 +- content/shell/shell_url_request_context_getter.cc | 4 +- .../glue/proxy_resolving_client_socket_unittest.cc | 2 +- .../communicator/single_login_attempt_unittest.cc | 2 +- net/base/host_resolver.cc | 148 -- net/base/host_resolver.h | 208 -- net/base/host_resolver_impl.cc | 2180 -------------------- net/base/host_resolver_impl.h | 287 --- net/base/host_resolver_impl_unittest.cc | 1481 ------------- net/base/host_resolver_proc.cc | 251 --- net/base/host_resolver_proc.h | 96 - net/base/mapped_host_resolver.cc | 67 - net/base/mapped_host_resolver.h | 72 - net/base/mapped_host_resolver_unittest.cc | 219 -- net/base/mock_host_resolver.cc | 417 ---- net/base/mock_host_resolver.h | 254 --- net/base/single_request_host_resolver.cc | 77 - net/base/single_request_host_resolver.h | 56 - net/base/single_request_host_resolver_unittest.cc | 124 -- net/dns/host_resolver.cc | 148 ++ net/dns/host_resolver.h | 208 ++ net/dns/host_resolver_impl.cc | 2180 ++++++++++++++++++++ net/dns/host_resolver_impl.h | 287 +++ net/dns/host_resolver_impl_unittest.cc | 1481 +++++++++++++ net/dns/host_resolver_proc.cc | 251 +++ net/dns/host_resolver_proc.h | 96 + net/dns/mapped_host_resolver.cc | 67 + net/dns/mapped_host_resolver.h | 72 + net/dns/mapped_host_resolver_unittest.cc | 219 ++ net/dns/mock_host_resolver.cc | 417 ++++ net/dns/mock_host_resolver.h | 254 +++ net/dns/single_request_host_resolver.cc | 77 + net/dns/single_request_host_resolver.h | 56 + net/dns/single_request_host_resolver_unittest.cc | 124 ++ net/ftp/ftp_network_transaction.h | 4 +- net/ftp/ftp_network_transaction_unittest.cc | 2 +- net/http/http_auth_controller.cc | 2 +- net/http/http_auth_handler_factory_unittest.cc | 2 +- net/http/http_auth_handler_negotiate.cc | 4 +- net/http/http_auth_handler_negotiate_unittest.cc | 2 +- net/http/http_auth_unittest.cc | 2 +- net/http/http_network_layer_unittest.cc | 2 +- net/http/http_network_session.h | 2 +- .../http_network_transaction_spdy2_unittest.cc | 2 +- .../http_network_transaction_spdy3_unittest.cc | 2 +- .../http_pipelined_network_transaction_unittest.cc | 2 +- net/http/http_stream_factory_impl_unittest.cc | 2 +- net/net.gyp | 30 +- net/proxy/proxy_resolver_perftest.cc | 2 +- net/proxy/proxy_resolver_v8_tracing.cc | 2 +- net/proxy/proxy_resolver_v8_tracing_unittest.cc | 2 +- net/proxy/proxy_script_fetcher_impl_unittest.cc | 2 +- net/quic/quic_network_transaction_unittest.cc | 2 +- net/quic/quic_stream_factory.cc | 4 +- net/quic/quic_stream_factory_test.cc | 2 +- net/socket/client_socket_pool.h | 4 +- net/socket/socks5_client_socket.h | 2 +- net/socket/socks5_client_socket_unittest.cc | 2 +- net/socket/socks_client_socket.h | 4 +- net/socket/socks_client_socket_pool.h | 4 +- net/socket/socks_client_socket_pool_unittest.cc | 2 +- net/socket/socks_client_socket_unittest.cc | 4 +- net/socket/ssl_client_socket_openssl_unittest.cc | 2 +- net/socket/ssl_client_socket_pool.h | 2 +- net/socket/ssl_client_socket_pool_unittest.cc | 2 +- net/socket/ssl_client_socket_unittest.cc | 2 +- net/socket/transport_client_socket_pool.h | 6 +- .../transport_client_socket_pool_unittest.cc | 2 +- net/socket/transport_client_socket_unittest.cc | 4 +- net/socket_stream/socket_stream.cc | 2 +- net/socket_stream/socket_stream_unittest.cc | 2 +- .../spdy_proxy_client_socket_spdy2_unittest.cc | 8 +- .../spdy_proxy_client_socket_spdy3_unittest.cc | 8 +- net/spdy/spdy_test_util_spdy2.h | 2 +- net/spdy/spdy_test_util_spdy3.h | 2 +- net/test/base_test_server.cc | 2 +- net/test/net_test_suite.h | 2 +- net/tools/fetch/fetch_client.cc | 2 +- net/tools/gdig/gdig.cc | 2 +- net/url_request/url_fetcher_impl_unittest.cc | 2 +- net/url_request/url_request_context.cc | 2 +- net/url_request/url_request_context_builder.cc | 2 +- net/url_request/url_request_context_storage.cc | 2 +- net/url_request/url_request_test_util.cc | 2 +- net/url_request/url_request_unittest.cc | 2 +- net/websockets/websocket_job_spdy2_unittest.cc | 2 +- net/websockets/websocket_job_spdy3_unittest.cc | 2 +- remoting/host/DEPS | 1 + remoting/host/url_request_context.cc | 2 +- sync/internal_api/http_bridge.cc | 2 +- sync/tools/sync_client.cc | 2 +- sync/tools/sync_listen_notifications.cc | 2 +- webkit/DEPS | 1 + .../tools/test_shell/test_shell_request_context.cc | 2 +- 171 files changed, 6121 insertions(+), 6119 deletions(-) delete mode 100644 net/base/host_resolver.cc delete mode 100644 net/base/host_resolver.h delete mode 100644 net/base/host_resolver_impl.cc delete mode 100644 net/base/host_resolver_impl.h delete mode 100644 net/base/host_resolver_impl_unittest.cc delete mode 100644 net/base/host_resolver_proc.cc delete mode 100644 net/base/host_resolver_proc.h delete mode 100644 net/base/mapped_host_resolver.cc delete mode 100644 net/base/mapped_host_resolver.h delete mode 100644 net/base/mapped_host_resolver_unittest.cc delete mode 100644 net/base/mock_host_resolver.cc delete mode 100644 net/base/mock_host_resolver.h delete mode 100644 net/base/single_request_host_resolver.cc delete mode 100644 net/base/single_request_host_resolver.h delete mode 100644 net/base/single_request_host_resolver_unittest.cc create mode 100644 net/dns/host_resolver.cc create mode 100644 net/dns/host_resolver.h create mode 100644 net/dns/host_resolver_impl.cc create mode 100644 net/dns/host_resolver_impl.h create mode 100644 net/dns/host_resolver_impl_unittest.cc create mode 100644 net/dns/host_resolver_proc.cc create mode 100644 net/dns/host_resolver_proc.h create mode 100644 net/dns/mapped_host_resolver.cc create mode 100644 net/dns/mapped_host_resolver.h create mode 100644 net/dns/mapped_host_resolver_unittest.cc create mode 100644 net/dns/mock_host_resolver.cc create mode 100644 net/dns/mock_host_resolver.h create mode 100644 net/dns/single_request_host_resolver.cc create mode 100644 net/dns/single_request_host_resolver.h create mode 100644 net/dns/single_request_host_resolver_unittest.cc diff --git a/chrome/browser/chrome_net_benchmarking_message_filter.cc b/chrome/browser/chrome_net_benchmarking_message_filter.cc index abe3652..f98e9c3 100644 --- a/chrome/browser/chrome_net_benchmarking_message_filter.cc +++ b/chrome/browser/chrome_net_benchmarking_message_filter.cc @@ -14,9 +14,9 @@ #include "chrome/common/benchmarking_messages.h" #include "chrome/common/chrome_switches.h" #include "net/base/host_cache.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/host_resolver.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_stream_factory.h" diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc index d52cf7e..9896582 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc @@ -16,7 +16,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "net/base/host_port_pair.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" namespace chromeos { diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc index 0f8466c..3c2b3ef 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_apitest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_WallpaperPicker) { host_resolver()->AddRule("a.com", "127.0.0.1"); diff --git a/chrome/browser/extensions/activity_log_browsertest.cc b/chrome/browser/extensions/activity_log_browsertest.cc index 52bfaa2..8450603 100644 --- a/chrome/browser/extensions/activity_log_browsertest.cc +++ b/chrome/browser/extensions/activity_log_browsertest.cc @@ -8,7 +8,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" // Used to fire all of the listeners on the buttons. static const char kScriptClickAllTestButtons[] = diff --git a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc index 077e412..ea4b893 100644 --- a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc +++ b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc @@ -10,7 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/extensions/api/dns/dns_api.h b/chrome/browser/extensions/api/dns/dns_api.h index 1c646f6..56a0785 100644 --- a/chrome/browser/extensions/api/dns/dns_api.h +++ b/chrome/browser/extensions/api/dns/dns_api.h @@ -11,7 +11,7 @@ #include "chrome/browser/io_thread.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" class IOThread; diff --git a/chrome/browser/extensions/api/dns/dns_apitest.cc b/chrome/browser/extensions/api/dns/dns_apitest.cc index ce8cbab..3671879 100644 --- a/chrome/browser/extensions/api/dns/dns_apitest.cc +++ b/chrome/browser/extensions/api/dns/dns_apitest.cc @@ -10,9 +10,9 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/common/chrome_switches.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" +#include "net/dns/mock_host_resolver.h" using extension_function_test_utils::CreateEmptyExtension; using extension_function_test_utils::RunFunctionAndReturnSingleResult; diff --git a/chrome/browser/extensions/api/dns/host_resolver_wrapper.h b/chrome/browser/extensions/api/dns/host_resolver_wrapper.h index 35c9e52..ea8dc9d 100644 --- a/chrome/browser/extensions/api/dns/host_resolver_wrapper.h +++ b/chrome/browser/extensions/api/dns/host_resolver_wrapper.h @@ -6,7 +6,7 @@ #define CHROME_BROWSER_EXTENSIONS_API_DNS_HOST_RESOLVER_WRAPPER_H_ #include "base/memory/singleton.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" namespace extensions { diff --git a/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc b/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc index 03ba155..fa49956 100644 --- a/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc +++ b/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc @@ -6,7 +6,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/browser_thread.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::BrowserThread; diff --git a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc index 959874c..fd32e96 100644 --- a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc +++ b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc @@ -18,7 +18,7 @@ #include "chrome/common/extensions/features/feature.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chrome/browser/extensions/api/history/history_apitest.cc b/chrome/browser/extensions/api/history/history_apitest.cc index a032dc2..800aef6 100644 --- a/chrome/browser/extensions/api/history/history_apitest.cc +++ b/chrome/browser/extensions/api/history/history_apitest.cc @@ -15,7 +15,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" namespace extensions { diff --git a/chrome/browser/extensions/api/idle/idle_apitest.cc b/chrome/browser/extensions/api/idle/idle_apitest.cc index 63edad7..64d7515 100644 --- a/chrome/browser/extensions/api/idle/idle_apitest.cc +++ b/chrome/browser/extensions/api/idle/idle_apitest.cc @@ -4,7 +4,7 @@ #include "base/command_line.h" #include "chrome/browser/extensions/extension_apitest.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" // This test is flaky: crbug.com/130138 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_Idle) { diff --git a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc index e0a7ad8..34e7654 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc +++ b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc @@ -4,11 +4,11 @@ #include "base/base_switches.h" #include "base/command_line.h" -#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/api/page_capture/page_capture_api.h" +#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using extensions::PageCaptureSaveAsMHTMLFunction; diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc index 5b28864..73ec0fa 100644 --- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc +++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc @@ -10,7 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/permissions/permission_set.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using extensions::APIPermission; using extensions::APIPermissionSet; diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc index d56d123..13d7233 100644 --- a/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc +++ b/chrome/browser/extensions/api/push_messaging/push_messaging_canary_test.cc @@ -16,7 +16,7 @@ #include "chrome/common/extensions/extension_set.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_view_host.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" namespace { const char kTestExtensionId[] = "mfaehphpebmlbfdiegjnpidmibldjbjk"; diff --git a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h index 808c08d..886f0f0 100644 --- a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h +++ b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.h @@ -11,7 +11,7 @@ #include "base/compiler_specific.h" #include "base/file_util.h" #include "base/memory/scoped_ptr.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" class Profile; class ProfileSyncServiceHarness; diff --git a/chrome/browser/extensions/api/socket/socket_api.h b/chrome/browser/extensions/api/socket/socket_api.h index b26e748..34013a4 100644 --- a/chrome/browser/extensions/api/socket/socket_api.h +++ b/chrome/browser/extensions/api/socket/socket_api.h @@ -11,7 +11,7 @@ #include "chrome/browser/extensions/extension_function.h" #include "chrome/common/extensions/api/socket.h" #include "net/base/address_list.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" #include "net/socket/tcp_client_socket.h" #include diff --git a/chrome/browser/extensions/api/socket/socket_apitest.cc b/chrome/browser/extensions/api/socket/socket_apitest.cc index 73e62fa..7921ce9 100644 --- a/chrome/browser/extensions/api/socket/socket_apitest.cc +++ b/chrome/browser/extensions/api/socket/socket_apitest.cc @@ -15,7 +15,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" using extensions::Extension; diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc index 42a1e92..d599ede 100644 --- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc +++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc @@ -7,8 +7,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/utf_string_conversions.h" #include "base/stringprintf.h" +#include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_browser_main.h" @@ -36,7 +36,7 @@ #include "content/public/common/context_menu_params.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" #include "webkit/glue/resource_type.h" diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc index 12ff0e2..0e03c64 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc @@ -39,11 +39,11 @@ #include "content/public/test/test_browser_thread.h" #include "net/base/auth.h" #include "net/base/capturing_net_log.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_util.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" +#include "net/dns/mock_host_resolver.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest-message.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 8b115d8..c64d0bd 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc @@ -21,7 +21,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" using content::WebContents; diff --git a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc index 3209c7a..237941c 100644 --- a/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc +++ b/chrome/browser/extensions/api/web_socket_proxy_private/web_socket_proxy_private_api.cc @@ -20,7 +20,7 @@ #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_util.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/web_socket_proxy_controller.h" diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index 5391317..360dd34 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc @@ -28,7 +28,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/common/gpu_info.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "ui/gl/gl_switches.h" using content::GpuFeatureType; diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc index af85b86..ec55fcf 100644 --- a/chrome/browser/extensions/app_background_page_apitest.cc +++ b/chrome/browser/extensions/app_background_page_apitest.cc @@ -18,7 +18,7 @@ #include "content/public/browser/notification_service.h" #include "content/public/test/test_notification_tracker.h" #include "content/public/test/test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using extensions::Extension; diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index 53c1455..39fc84f 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -27,7 +27,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "sync/api/string_ordinal.h" using content::NavigationController; diff --git a/chrome/browser/extensions/chrome_app_api_browsertest.cc b/chrome/browser/extensions/chrome_app_api_browsertest.cc index a961366..3103e6f 100644 --- a/chrome/browser/extensions/chrome_app_api_browsertest.cc +++ b/chrome/browser/extensions/chrome_app_api_browsertest.cc @@ -21,7 +21,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using extensions::Extension; diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc index bbee2a4..f3d5035 100644 --- a/chrome/browser/extensions/content_script_apitest.cc +++ b/chrome/browser/extensions/content_script_apitest.cc @@ -15,7 +15,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) { ASSERT_TRUE(StartTestServer()); diff --git a/chrome/browser/extensions/content_security_policy_apitest.cc b/chrome/browser/extensions/content_security_policy_apitest.cc index 1740e2e..d2a4969 100644 --- a/chrome/browser/extensions/content_security_policy_apitest.cc +++ b/chrome/browser/extensions/content_security_policy_apitest.cc @@ -4,7 +4,7 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/common/chrome_switches.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentSecurityPolicy) { ASSERT_TRUE(StartTestServer()); diff --git a/chrome/browser/extensions/cross_origin_xhr_apitest.cc b/chrome/browser/extensions/cross_origin_xhr_apitest.cc index 8c24606..4198b7d 100644 --- a/chrome/browser/extensions/cross_origin_xhr_apitest.cc +++ b/chrome/browser/extensions/cross_origin_xhr_apitest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CrossOriginXHRBackgroundPage) { host_resolver()->AddRule("*.com", "127.0.0.1"); diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc index d2861a7..2c081f1 100644 --- a/chrome/browser/extensions/execute_script_apitest.cc +++ b/chrome/browser/extensions/execute_script_apitest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" class ExecuteScriptApiTest : public ExtensionApiTest { protected: diff --git a/chrome/browser/extensions/extension_context_menu_browsertest.cc b/chrome/browser/extensions/extension_context_menu_browsertest.cc index 90c2e67..1ea9ef5 100644 --- a/chrome/browser/extensions/extension_context_menu_browsertest.cc +++ b/chrome/browser/extensions/extension_context_menu_browsertest.cc @@ -17,7 +17,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/common/context_menu_params.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h" #include "ui/base/models/menu_model.h" diff --git a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc index a0c1544..4d7bdfb 100644 --- a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc +++ b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc @@ -10,7 +10,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" namespace { diff --git a/chrome/browser/extensions/extension_icon_source_apitest.cc b/chrome/browser/extensions/extension_icon_source_apitest.cc index 9c5c4b8..0dd5064 100644 --- a/chrome/browser/extensions/extension_icon_source_apitest.cc +++ b/chrome/browser/extensions/extension_icon_source_apitest.cc @@ -13,7 +13,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" class ExtensionIconSourceTest : public ExtensionApiTest { protected: diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc index a4f9ae1..0e21345 100644 --- a/chrome/browser/extensions/extension_incognito_apitest.cc +++ b/chrome/browser/extensions/extension_incognito_apitest.cc @@ -15,7 +15,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::WebContents; diff --git a/chrome/browser/extensions/extension_javascript_url_apitest.cc b/chrome/browser/extensions/extension_javascript_url_apitest.cc index 8a845e3..4076c145 100644 --- a/chrome/browser/extensions/extension_javascript_url_apitest.cc +++ b/chrome/browser/extensions/extension_javascript_url_apitest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" // If crashing, mark disabled and update http://crbug.com/63589. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, JavaScriptURLPermissions) { diff --git a/chrome/browser/extensions/extension_nacl_browsertest.cc b/chrome/browser/extensions/extension_nacl_browsertest.cc index 5c4f224..afb4c64 100644 --- a/chrome/browser/extensions/extension_nacl_browsertest.cc +++ b/chrome/browser/extensions/extension_nacl_browsertest.cc @@ -21,7 +21,7 @@ #include "content/public/browser/plugin_service.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "webkit/plugins/webplugininfo.h" using content::PluginService; diff --git a/chrome/browser/extensions/extension_resource_request_policy_apitest.cc b/chrome/browser/extensions/extension_resource_request_policy_apitest.cc index 3ccd727..f8ce956 100644 --- a/chrome/browser/extensions/extension_resource_request_policy_apitest.cc +++ b/chrome/browser/extensions/extension_resource_request_policy_apitest.cc @@ -11,7 +11,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" class ExtensionResourceRequestPolicyTest : public ExtensionApiTest { protected: diff --git a/chrome/browser/extensions/extension_tabs_apitest.cc b/chrome/browser/extensions/extension_tabs_apitest.cc index 2b748de..7927289 100644 --- a/chrome/browser/extensions/extension_tabs_apitest.cc +++ b/chrome/browser/extensions/extension_tabs_apitest.cc @@ -12,7 +12,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" // Possible race in ChromeURLDataManager. http://crbug.com/59198 #if defined(OS_MACOSX) || defined(OS_LINUX) diff --git a/chrome/browser/extensions/extension_websocket_apitest.cc b/chrome/browser/extensions/extension_websocket_apitest.cc index 16307fb..f71ddb9 100644 --- a/chrome/browser/extensions/extension_websocket_apitest.cc +++ b/chrome/browser/extensions/extension_websocket_apitest.cc @@ -5,8 +5,8 @@ #include "base/path_service.h" #include "chrome/browser/extensions/extension_apitest.h" #include "content/public/common/content_paths.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_data_directory.h" +#include "net/dns/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, WebSocket) { ASSERT_TRUE(StartWebSocketServer(net::GetWebSocketTestDataDirectory())); diff --git a/chrome/browser/extensions/isolated_app_browsertest.cc b/chrome/browser/extensions/isolated_app_browsertest.cc index 3d8712a..b7717bb 100644 --- a/chrome/browser/extensions/isolated_app_browsertest.cc +++ b/chrome/browser/extensions/isolated_app_browsertest.cc @@ -20,7 +20,7 @@ #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::ExecuteScript; using content::ExecuteScriptAndExtractString; diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc index f35694e..685e488 100644 --- a/chrome/browser/extensions/lazy_background_page_apitest.cc +++ b/chrome/browser/extensions/lazy_background_page_apitest.cc @@ -29,7 +29,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using extensions::Extension; diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc index 4e07bc1..ecafade 100644 --- a/chrome/browser/extensions/process_management_browsertest.cc +++ b/chrome/browser/extensions/process_management_browsertest.cc @@ -19,7 +19,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::NavigationController; using content::WebContents; diff --git a/chrome/browser/extensions/webstore_startup_installer_browsertest.cc b/chrome/browser/extensions/webstore_startup_installer_browsertest.cc index 62ac4f9c..6f7fb56 100644 --- a/chrome/browser/extensions/webstore_startup_installer_browsertest.cc +++ b/chrome/browser/extensions/webstore_startup_installer_browsertest.cc @@ -27,7 +27,7 @@ #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" #include "net/base/host_port_pair.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::WebContents; using extensions::DictionaryBuilder; diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc index 978f77c..5e2a0fc 100644 --- a/chrome/browser/extensions/window_open_apitest.cc +++ b/chrome/browser/extensions/window_open_apitest.cc @@ -22,7 +22,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/result_codes.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(USE_ASH) diff --git a/chrome/browser/intranet_redirect_detector.h b/chrome/browser/intranet_redirect_detector.h index 5518234..68ef522 100644 --- a/chrome/browser/intranet_redirect_detector.h +++ b/chrome/browser/intranet_redirect_detector.h @@ -13,8 +13,8 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "googleurl/src/gurl.h" -#include "net/base/host_resolver_proc.h" #include "net/base/network_change_notifier.h" +#include "net/dns/host_resolver_proc.h" #include "net/url_request/url_fetcher_delegate.h" class PrefRegistrySimple; diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 40ed1d4..bff0283 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -43,11 +43,11 @@ #include "net/base/cert_verifier.h" #include "net/base/host_cache.h" #include "net/base/host_mapping_rules.h" -#include "net/base/host_resolver.h" -#include "net/base/mapped_host_resolver.h" #include "net/base/net_util.h" #include "net/base/sdch_manager.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" +#include "net/dns/mapped_host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_filter.h" #include "net/http/http_auth_handler_factory.h" diff --git a/chrome/browser/net/connection_tester.cc b/chrome/browser/net/connection_tester.cc index 34906a6..384b26a 100644 --- a/chrome/browser/net/connection_tester.cc +++ b/chrome/browser/net/connection_tester.cc @@ -16,11 +16,11 @@ #include "chrome/common/chrome_switches.h" #include "content/public/browser/browser_thread.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" diff --git a/chrome/browser/net/connection_tester_unittest.cc b/chrome/browser/net/connection_tester_unittest.cc index a482ca1..5b40ef4 100644 --- a/chrome/browser/net/connection_tester_unittest.cc +++ b/chrome/browser/net/connection_tester_unittest.cc @@ -7,8 +7,8 @@ #include "base/prefs/testing_pref_service.h" #include "content/public/test/test_browser_thread.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/mock_host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_layer.h" diff --git a/chrome/browser/net/cookie_policy_browsertest.cc b/chrome/browser/net/cookie_policy_browsertest.cc index 2fb5fa5..5a5ba24 100644 --- a/chrome/browser/net/cookie_policy_browsertest.cc +++ b/chrome/browser/net/cookie_policy_browsertest.cc @@ -13,7 +13,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" using content::BrowserThread; diff --git a/chrome/browser/net/network_stats.h b/chrome/browser/net/network_stats.h index 7e008d9..de01790 100644 --- a/chrome/browser/net/network_stats.h +++ b/chrome/browser/net/network_stats.h @@ -17,10 +17,10 @@ #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/test_data_stream.h" +#include "net/dns/host_resolver.h" #include "net/proxy/proxy_info.h" #include "net/socket/socket.h" diff --git a/chrome/browser/net/network_stats_unittest.cc b/chrome/browser/net/network_stats_unittest.cc index e3c1a4a..99dffb2 100644 --- a/chrome/browser/net/network_stats_unittest.cc +++ b/chrome/browser/net/network_stats_unittest.cc @@ -6,10 +6,10 @@ #include "base/message_loop.h" #include "base/stringprintf.h" #include "chrome/browser/net/network_stats.h" -#include "net/base/host_resolver.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/dns/host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index 0e3bbd8..6e82188 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc @@ -33,10 +33,10 @@ #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/url_request/url_request_context_getter.h" using base::TimeDelta; diff --git a/chrome/browser/net/predictor_browsertest.cc b/chrome/browser/net/predictor_browsertest.cc index 3182b8c..b2a00c7 100644 --- a/chrome/browser/net/predictor_browsertest.cc +++ b/chrome/browser/net/predictor_browsertest.cc @@ -10,9 +10,9 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "net/base/host_resolver_proc.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" +#include "net/dns/host_resolver_proc.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gmock/include/gmock/gmock.h" using content::BrowserThread; diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc index dae3af3..f509e1c 100644 --- a/chrome/browser/net/predictor_unittest.cc +++ b/chrome/browser/net/predictor_unittest.cc @@ -18,8 +18,8 @@ #include "chrome/common/net/predictor_common.h" #include "content/public/test/test_browser_thread.h" #include "net/base/address_list.h" -#include "net/base/mock_host_resolver.h" #include "net/base/winsock_init.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; diff --git a/chrome/browser/policy/cloud/device_management_service.cc b/chrome/browser/policy/cloud/device_management_service.cc index bbefd1d..07a8df2 100644 --- a/chrome/browser/policy/cloud/device_management_service.cc +++ b/chrome/browser/policy/cloud/device_management_service.cc @@ -20,10 +20,10 @@ #include "content/public/common/content_client.h" #include "googleurl/src/gurl.h" #include "net/base/escape.h" -#include "net/base/host_resolver.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/http/http_network_layer.h" #include "net/http/http_response_headers.h" #include "net/proxy/proxy_service.h" diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 78439db..bc7d22b 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -56,7 +56,7 @@ #include "content/public/test/test_utils.h" #include "googleurl/src/gurl.h" #include "grit/generated_resources.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "ui/base/l10n/l10n_util.h" diff --git a/chrome/browser/rlz/rlz_extension_apitest.cc b/chrome/browser/rlz/rlz_extension_apitest.cc index dca0967..bb06299 100644 --- a/chrome/browser/rlz/rlz_extension_apitest.cc +++ b/chrome/browser/rlz/rlz_extension_apitest.cc @@ -5,13 +5,13 @@ #include #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_function.h" #include "chrome/browser/extensions/extension_function_dispatcher.h" -#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/rlz/rlz_extension_api.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "rlz/lib/rlz_lib.h" #if (OS_WIN) diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc index 47a7f99..d25ebe4 100644 --- a/chrome/browser/safe_browsing/safe_browsing_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_test.cc @@ -44,9 +44,9 @@ #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_context.h" #include "content/public/test/test_browser_thread.h" -#include "net/base/host_resolver.h" #include "net/base/load_flags.h" #include "net/base/net_log.h" +#include "net/dns/host_resolver.h" #include "net/test/python_utils.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher_delegate.h" diff --git a/chrome/browser/search_engines/template_url_scraper_unittest.cc b/chrome/browser/search_engines/template_url_scraper_unittest.cc index be62ded..999c525 100644 --- a/chrome/browser/search_engines/template_url_scraper_unittest.cc +++ b/chrome/browser/search_engines/template_url_scraper_unittest.cc @@ -3,17 +3,17 @@ // found in the LICENSE file. #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_prepopulate_data.h" #include "chrome/browser/search_engines/template_url_service.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/search_engines/template_url_prepopulate_data.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_source.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_util.h" +#include "net/dns/mock_host_resolver.h" namespace { class TemplateURLScraperTest : public InProcessBrowserTest { diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index 1d16691..3fe583f 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h @@ -16,7 +16,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/process_util.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync_protocol_error.h" #include "sync/test/local_sync_test_server.h" diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index 47eeac0..a293372 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc @@ -37,7 +37,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/page_transition_types.h" #include "grit/generated_resources.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 80a823c..799040d 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc @@ -66,7 +66,7 @@ #include "content/public/test/test_navigation_observer.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" #include "ui/base/l10n/l10n_util.h" diff --git a/chrome/browser/ui/login/login_prompt_browsertest.cc b/chrome/browser/ui/login/login_prompt_browsertest.cc index 0c104bc..6291815 100644 --- a/chrome/browser/ui/login/login_prompt_browsertest.cc +++ b/chrome/browser/ui/login/login_prompt_browsertest.cc @@ -20,7 +20,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "net/base/auth.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" using content::NavigationController; using content::OpenURLParams; diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index a417cb5..2af3ec1 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc @@ -37,7 +37,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/events/event_constants.h" #include "ui/base/keycodes/keyboard_codes.h" diff --git a/chrome/browser/ui/search/instant_extended_manual_browsertest.cc b/chrome/browser/ui/search/instant_extended_manual_browsertest.cc index c0e277d..225e089 100644 --- a/chrome/browser/ui/search/instant_extended_manual_browsertest.cc +++ b/chrome/browser/ui/search/instant_extended_manual_browsertest.cc @@ -24,7 +24,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" // Instant extended tests that need to be run manually because they need to // talk to the external network. All tests in this file should be marked as diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc index 3bb1d48..4f82a4d 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc @@ -57,10 +57,10 @@ #include "grit/generated_resources.h" #include "grit/net_internals_resources.h" #include "net/base/host_cache.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/host_resolver.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc index c88584d..9672637 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc @@ -23,9 +23,9 @@ #include "googleurl/src/gurl.h" #include "net/base/address_list.h" #include "net/base/host_cache.h" -#include "net/base/host_resolver.h" -#include "net/base/host_resolver_proc.h" #include "net/base/net_errors.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_proc.h" #include "net/http/http_network_session.h" #include "net/http/http_pipelined_host_capability.h" #include "net/http/http_transaction_factory.h" diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index edc99bc..7e7bbb3 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -31,7 +31,7 @@ #include "extensions/common/error_utils.h" #include "googleurl/src/gurl.h" #include "net/base/mime_sniffer.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "skia/ext/image_operations.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" diff --git a/chrome/service/net/service_url_request_context.cc b/chrome/service/net/service_url_request_context.cc index cc8bacb..5fdee43 100644 --- a/chrome/service/net/service_url_request_context.cc +++ b/chrome/service/net/service_url_request_context.cc @@ -15,8 +15,8 @@ #include "chrome/common/chrome_version_info.h" #include "chrome/service/service_process.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" diff --git a/chrome/service/net/service_url_request_context.h b/chrome/service/net/service_url_request_context.h index 6bcc7e0..c409ede 100644 --- a/chrome/service/net/service_url_request_context.h +++ b/chrome/service/net/service_url_request_context.h @@ -8,9 +8,9 @@ #include #include "base/memory/scoped_ptr.h" -#include "net/base/host_resolver.h" #include "net/cookies/cookie_monster.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc index ca41120..26d359e 100644 --- a/chrome/test/base/chrome_test_suite.cc +++ b/chrome/test/base/chrome_test_suite.cc @@ -26,9 +26,9 @@ #include "chrome/common/url_constants.h" #include "chrome/test/base/testing_browser_process.h" #include "content/public/test/test_launcher.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_handle.h" diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index 53aad1c..fb99e8f 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc @@ -44,7 +44,7 @@ #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_launcher.h" #include "content/public/test/test_navigation_observer.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/test_server.h" #include "ui/compositor/compositor_switches.h" diff --git a/chrome/test/perf/rendering/throughput_tests.cc b/chrome/test/perf/rendering/throughput_tests.cc index f9bfefe..79d6bbb 100644 --- a/chrome/test/perf/rendering/throughput_tests.cc +++ b/chrome/test/perf/rendering/throughput_tests.cc @@ -32,8 +32,8 @@ #include "content/public/test/test_utils.h" #include "content/test/gpu/gpu_test_config.h" #include "googleurl/src/gurl.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_util.h" +#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" diff --git a/chrome_frame/test/test_server_test.cc b/chrome_frame/test/test_server_test.cc index a489a83..f893e7a 100644 --- a/chrome_frame/test/test_server_test.cc +++ b/chrome_frame/test/test_server_test.cc @@ -11,9 +11,9 @@ #include "base/stringprintf.h" #include "base/win/scoped_handle.h" #include "chrome_frame/test/test_server.h" -#include "net/base/host_resolver_proc.h" #include "net/cookies/cookie_monster.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/host_resolver_proc.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc index 7b8151d..7c79711 100644 --- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc +++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc @@ -7,14 +7,14 @@ #include "base/bind.h" #include "base/stl_util.h" #include "content/browser/renderer_host/p2p/socket_host.h" -#include "content/public/browser/resource_context.h" #include "content/common/p2p_messages.h" +#include "content/public/browser/resource_context.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" -#include "net/base/single_request_host_resolver.h" #include "net/base/sys_addrinfo.h" +#include "net/dns/single_request_host_resolver.h" using content::BrowserMessageFilter; using content::BrowserThread; diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc b/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc index 05aa6f8..c04aafe 100644 --- a/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_host_resolver_private_message_filter.cc @@ -15,7 +15,7 @@ #include "content/public/browser/resource_context.h" #include "content/public/common/socket_permission_request.h" #include "net/base/address_list.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_host_resolver_private.h" #include "ppapi/c/private/ppb_net_address_private.h" diff --git a/content/browser/renderer_host/pepper/pepper_lookup_request.h b/content/browser/renderer_host/pepper/pepper_lookup_request.h index f08a02b..bcb9a60 100644 --- a/content/browser/renderer_host/pepper/pepper_lookup_request.h +++ b/content/browser/renderer_host/pepper/pepper_lookup_request.h @@ -8,9 +8,9 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "net/base/address_list.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" namespace content { diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc index baa60e3..e6732e5 100644 --- a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc +++ b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc @@ -15,12 +15,12 @@ #include "content/public/browser/browser_thread.h" #include "net/base/cert_verifier.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" -#include "net/base/single_request_host_resolver.h" #include "net/base/x509_certificate.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/ssl_client_socket.h" diff --git a/content/shell/shell_url_request_context_getter.cc b/content/shell/shell_url_request_context_getter.cc index 70a3dae..88dd801 100644 --- a/content/shell/shell_url_request_context_getter.cc +++ b/content/shell/shell_url_request_context_getter.cc @@ -16,9 +16,9 @@ #include "content/shell/shell_network_delegate.h" #include "content/shell/shell_switches.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" -#include "net/base/mapped_host_resolver.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" +#include "net/dns/mapped_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" diff --git a/jingle/glue/proxy_resolving_client_socket_unittest.cc b/jingle/glue/proxy_resolving_client_socket_unittest.cc index 682c543..834d7d24 100644 --- a/jingle/glue/proxy_resolving_client_socket_unittest.cc +++ b/jingle/glue/proxy_resolving_client_socket_unittest.cc @@ -7,8 +7,8 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/message_loop.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/proxy/proxy_service.h" #include "net/socket/socket_test_util.h" #include "net/url_request/url_request_context_getter.h" diff --git a/jingle/notifier/communicator/single_login_attempt_unittest.cc b/jingle/notifier/communicator/single_login_attempt_unittest.cc index 20a9bf7..582b808 100644 --- a/jingle/notifier/communicator/single_login_attempt_unittest.cc +++ b/jingle/notifier/communicator/single_login_attempt_unittest.cc @@ -12,7 +12,7 @@ #include "jingle/notifier/base/const_communicator.h" #include "jingle/notifier/base/fake_base_task.h" #include "jingle/notifier/communicator/login_settings.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/url_request/url_request_test_util.h" #include "talk/xmllite/xmlelement.h" #include "talk/xmpp/constants.h" diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc deleted file mode 100644 index 7d98dd6..0000000 --- a/net/base/host_resolver.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2012 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.h" - -#include "base/logging.h" -#include "base/metrics/field_trial.h" -#include "base/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "net/base/host_cache.h" -#include "net/base/host_resolver_impl.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_config_service.h" - -namespace net { - -namespace { - -// Maximum of 6 concurrent resolver threads (excluding retries). -// Some routers (or resolvers) appear to start to provide host-not-found if -// too many simultaneous resolutions are pending. This number needs to be -// further optimized, but 8 is what FF currently does. We found some routers -// that limit this to 6, so we're temporarily holding it at that level. -const size_t kDefaultMaxProcTasks = 6u; - -// When configuring from field trial, do not allow -const size_t kSaneMaxProcTasks = 20u; - -PrioritizedDispatcher::Limits GetDispatcherLimits( - const HostResolver::Options& options) { - PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, - options.max_concurrent_resolves); - - // If not using default, do not use the field trial. - if (limits.total_jobs != HostResolver::kDefaultParallelism) - return limits; - - // Default, without trial is no reserved slots. - limits.total_jobs = kDefaultMaxProcTasks; - - // Parallelism is determined by the field trial. - std::string group = base::FieldTrialList::FindFullName( - "HostResolverDispatch"); - - if (group.empty()) - return limits; - - // The format of the group name is a list of non-negative integers separated - // by ':'. Each of the elements in the list corresponds to an element in - // |reserved_slots|, except the last one which is the |total_jobs|. - - std::vector group_parts; - base::SplitString(group, ':', &group_parts); - if (group_parts.size() != NUM_PRIORITIES + 1) { - NOTREACHED(); - return limits; - } - - std::vector parsed(group_parts.size()); - size_t total_reserved_slots = 0; - - for (size_t i = 0; i < group_parts.size(); ++i) { - if (!base::StringToSizeT(group_parts[i], &parsed[i])) { - NOTREACHED(); - return limits; - } - } - - size_t total_jobs = parsed.back(); - parsed.pop_back(); - for (size_t i = 0; i < parsed.size(); ++i) { - total_reserved_slots += parsed[i]; - } - - // There must be some unreserved slots available for the all priorities. - if (total_reserved_slots > total_jobs || - (total_reserved_slots == total_jobs && parsed[MINIMUM_PRIORITY] == 0)) { - NOTREACHED(); - return limits; - } - - limits.total_jobs = total_jobs; - limits.reserved_slots = parsed; - return limits; -} - -} // namespace - -HostResolver::Options::Options() - : max_concurrent_resolves(kDefaultParallelism), - max_retry_attempts(kDefaultRetryAttempts), - enable_caching(true) { -} - -HostResolver::RequestInfo::RequestInfo(const HostPortPair& host_port_pair) - : host_port_pair_(host_port_pair), - address_family_(ADDRESS_FAMILY_UNSPECIFIED), - host_resolver_flags_(0), - allow_cached_response_(true), - is_speculative_(false), - priority_(MEDIUM) { -} - -HostResolver::~HostResolver() { -} - -AddressFamily HostResolver::GetDefaultAddressFamily() const { - return ADDRESS_FAMILY_UNSPECIFIED; -} - -void HostResolver::ProbeIPv6Support() { -} - -void HostResolver::SetDnsClientEnabled(bool enabled) { -} - -HostCache* HostResolver::GetHostCache() { - return NULL; -} - -base::Value* HostResolver::GetDnsConfigAsValue() const { - return NULL; -} - -// static -scoped_ptr -HostResolver::CreateSystemResolver(const Options& options, NetLog* net_log) { - scoped_ptr cache; - if (options.enable_caching) - cache = HostCache::CreateDefaultCache(); - return scoped_ptr(new HostResolverImpl( - cache.Pass(), - GetDispatcherLimits(options), - HostResolverImpl::ProcTaskParams(NULL, options.max_retry_attempts), - net_log)); -} - -// static -scoped_ptr -HostResolver::CreateDefaultResolver(NetLog* net_log) { - return CreateSystemResolver(Options(), net_log); -} - -HostResolver::HostResolver() { -} - -} // namespace net diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h deleted file mode 100644 index b697dc2..0000000 --- a/net/base/host_resolver.h +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2012 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_H_ -#define NET_BASE_HOST_RESOLVER_H_ - -#include - -#include "base/memory/scoped_ptr.h" -#include "net/base/address_family.h" -#include "net/base/completion_callback.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_export.h" -#include "net/base/net_util.h" -#include "net/base/request_priority.h" - -namespace base { -class Value; -} - -namespace net { - -class AddressList; -class BoundNetLog; -class HostCache; -class HostResolverProc; -class NetLog; - -// This class represents the task of resolving hostnames (or IP address -// literal) to an AddressList object. -// -// 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). -class NET_EXPORT HostResolver { - public: - // |max_concurrent_resolves| is how many resolve requests will be allowed to - // run in parallel. Pass HostResolver::kDefaultParallelism to choose a - // default value. - // |max_retry_attempts| is the maximum number of times we will retry for host - // resolution. Pass HostResolver::kDefaultRetryAttempts to choose a default - // value. - // |enable_caching| controls whether a HostCache is used. - struct NET_EXPORT Options { - Options(); - - size_t max_concurrent_resolves; - size_t max_retry_attempts; - bool enable_caching; - }; - - // The parameters for doing a Resolve(). A hostname and port are required, - // the rest are optional (and have reasonable defaults). - class NET_EXPORT RequestInfo { - public: - explicit RequestInfo(const HostPortPair& host_port_pair); - - const HostPortPair& host_port_pair() const { return host_port_pair_; } - void set_host_port_pair(const HostPortPair& host_port_pair) { - host_port_pair_ = host_port_pair; - } - - int port() const { return host_port_pair_.port(); } - const std::string& hostname() const { return host_port_pair_.host(); } - - AddressFamily address_family() const { return address_family_; } - void set_address_family(AddressFamily address_family) { - address_family_ = address_family; - } - - HostResolverFlags host_resolver_flags() const { - return host_resolver_flags_; - } - void set_host_resolver_flags(HostResolverFlags host_resolver_flags) { - host_resolver_flags_ = host_resolver_flags; - } - - bool allow_cached_response() const { return allow_cached_response_; } - void set_allow_cached_response(bool b) { allow_cached_response_ = b; } - - bool is_speculative() const { return is_speculative_; } - void set_is_speculative(bool b) { is_speculative_ = b; } - - RequestPriority priority() const { return priority_; } - void set_priority(RequestPriority priority) { priority_ = priority; } - - private: - // The hostname to resolve, and the port to use in resulting sockaddrs. - HostPortPair host_port_pair_; - - // The address family to restrict results to. - AddressFamily address_family_; - - // Flags to use when resolving this request. - HostResolverFlags host_resolver_flags_; - - // Whether it is ok to return a result from the host cache. - bool allow_cached_response_; - - // Whether this request was started by the DNS prefetcher. - bool is_speculative_; - - // The priority for the request. - RequestPriority priority_; - }; - - // Opaque type used to cancel a request. - typedef void* RequestHandle; - - // This value can be passed into CreateSystemResolver as the - // |max_concurrent_resolves| parameter. It will select a default level of - // concurrency. - static const size_t kDefaultParallelism = 0; - - // This value can be passed into CreateSystemResolver as the - // |max_retry_attempts| parameter. - static const size_t kDefaultRetryAttempts = -1; - - // 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 ~HostResolver(); - - // Resolves the given hostname (or IP address literal), filling out the - // |addresses| object upon success. The |info.port| parameter will be set as - // the sin(6)_port field of the sockaddr_in{6} struct. Returns OK if - // successful or an error code upon failure. Returns - // ERR_NAME_NOT_RESOLVED if hostname is invalid, or if it is an - // incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6 - // literal). - // - // If the operation cannot be completed synchronously, ERR_IO_PENDING will - // be returned and the real result code will be passed to the completion - // callback. Otherwise the result code is returned immediately from this - // call. - // - // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to - // the async request. This handle is not valid after the request has - // completed. - // - // Profiling information for the request is saved to |net_log| if non-NULL. - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) = 0; - - // Resolves the given hostname (or IP address literal) out of cache or HOSTS - // file (if enabled) only. This is guaranteed to complete synchronously. - // This acts like |Resolve()| if the hostname is IP literal, or cached value - // or HOSTS entry exists. Otherwise, ERR_DNS_CACHE_MISS is returned. - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) = 0; - - // Cancels the specified request. |req| is the handle returned by Resolve(). - // After a request is canceled, its completion callback will not be called. - // CancelRequest must NOT be called after the request's completion callback - // has already run or the request was canceled. - virtual void CancelRequest(RequestHandle req) = 0; - - // Sets the default AddressFamily to use when requests have left it - // unspecified. For example, this could be used to restrict resolution - // results to AF_INET by passing in ADDRESS_FAMILY_IPV4, or to - // AF_INET6 by passing in ADDRESS_FAMILY_IPV6. - virtual void SetDefaultAddressFamily(AddressFamily address_family) {} - virtual AddressFamily GetDefaultAddressFamily() const; - - // Continuously observe whether IPv6 is supported, and set the allowable - // address family to IPv4 iff IPv6 is not supported. - virtual void ProbeIPv6Support(); - - // Enable or disable the built-in asynchronous DnsClient. - virtual void SetDnsClientEnabled(bool enabled); - - // Returns the HostResolverCache |this| uses, or NULL if there isn't one. - // Used primarily to clear the cache and for getting debug information. - virtual HostCache* GetHostCache(); - - // Returns the current DNS configuration |this| is using, as a Value, or NULL - // if it's configured to always use the system host resolver. Caller takes - // ownership of the returned Value. - virtual base::Value* GetDnsConfigAsValue() const; - - // 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). - static scoped_ptr CreateSystemResolver( - const Options& options, - NetLog* net_log); - - // As above, but uses default parameters. - static scoped_ptr CreateDefaultResolver(NetLog* net_log); - - protected: - HostResolver(); - - private: - DISALLOW_COPY_AND_ASSIGN(HostResolver); -}; - -} // namespace net - -#endif // NET_BASE_HOST_RESOLVER_H_ diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc deleted file mode 100644 index ba59569..0000000 --- a/net/base/host_resolver_impl.cc +++ /dev/null @@ -1,2180 +0,0 @@ -// Copyright (c) 2012 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 -#elif defined(OS_POSIX) -#include -#endif - -#include -#include -#include - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/debug/debugger.h" -#include "base/debug/stack_trace.h" -#include "base/message_loop_proxy.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" -#include "base/stl_util.h" -#include "base/string_util.h" -#include "base/threading/worker_pool.h" -#include "base/time.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "net/base/address_family.h" -#include "net/base/address_list.h" -#include "net/base/dns_reloader.h" -#include "net/base/host_port_pair.h" -#include "net/base/host_resolver_proc.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" -#include "net/base/net_util.h" -#include "net/dns/address_sorter.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_config_service.h" -#include "net/dns/dns_protocol.h" -#include "net/dns/dns_response.h" -#include "net/dns/dns_transaction.h" - -#if defined(OS_WIN) -#include "net/base/winsock_init.h" -#endif - -namespace net { - -namespace { - -// Limit the size of hostnames that will be resolved to combat issues in -// some platform's resolvers. -const size_t kMaxHostLength = 4096; - -// Default TTL for successful resolutions with ProcTask. -const unsigned kCacheEntryTTLSeconds = 60; - -// Default TTL for unsuccessful resolutions with ProcTask. -const unsigned kNegativeCacheEntryTTLSeconds = 0; - -// Minimum TTL for successful resolutions with DnsTask. -const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds; - -// Number of consecutive failures of DnsTask (with successful fallback) before -// the DnsClient is disabled until the next DNS change. -const unsigned kMaximumDnsFailures = 16; - -// We use a separate histogram name for each platform to facilitate the -// display of error codes by their symbolic name (since each platform has -// different mappings). -const char kOSErrorsForGetAddrinfoHistogramName[] = -#if defined(OS_WIN) - "Net.OSErrorsForGetAddrinfo_Win"; -#elif defined(OS_MACOSX) - "Net.OSErrorsForGetAddrinfo_Mac"; -#elif defined(OS_LINUX) - "Net.OSErrorsForGetAddrinfo_Linux"; -#else - "Net.OSErrorsForGetAddrinfo"; -#endif - -// Gets a list of the likely error codes that getaddrinfo() can return -// (non-exhaustive). These are the error codes that we will track via -// a histogram. -std::vector GetAllGetAddrinfoOSErrors() { - int os_errors[] = { -#if defined(OS_POSIX) -#if !defined(OS_FREEBSD) -#if !defined(OS_ANDROID) - // EAI_ADDRFAMILY has been declared obsolete in Android's and - // FreeBSD's netdb.h. - EAI_ADDRFAMILY, -#endif - // EAI_NODATA has been declared obsolete in FreeBSD's netdb.h. - EAI_NODATA, -#endif - EAI_AGAIN, - EAI_BADFLAGS, - EAI_FAIL, - EAI_FAMILY, - EAI_MEMORY, - EAI_NONAME, - EAI_SERVICE, - EAI_SOCKTYPE, - EAI_SYSTEM, -#elif defined(OS_WIN) - // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx - WSA_NOT_ENOUGH_MEMORY, - WSAEAFNOSUPPORT, - WSAEINVAL, - WSAESOCKTNOSUPPORT, - WSAHOST_NOT_FOUND, - WSANO_DATA, - WSANO_RECOVERY, - WSANOTINITIALISED, - WSATRY_AGAIN, - WSATYPE_NOT_FOUND, - // The following are not in doc, but might be to appearing in results :-(. - WSA_INVALID_HANDLE, -#endif - }; - - // Ensure all errors are positive, as histogram only tracks positive values. - for (size_t i = 0; i < arraysize(os_errors); ++i) { - os_errors[i] = std::abs(os_errors[i]); - } - - return base::CustomHistogram::ArrayToCustomRanges(os_errors, - arraysize(os_errors)); -} - -enum DnsResolveStatus { - RESOLVE_STATUS_DNS_SUCCESS = 0, - RESOLVE_STATUS_PROC_SUCCESS, - RESOLVE_STATUS_FAIL, - RESOLVE_STATUS_SUSPECT_NETBIOS, - RESOLVE_STATUS_MAX -}; - -void UmaAsyncDnsResolveStatus(DnsResolveStatus result) { - UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus", - result, - RESOLVE_STATUS_MAX); -} - -bool ResemblesNetBIOSName(const std::string& hostname) { - return (hostname.size() < 16) && (hostname.find('.') == std::string::npos); -} - -// True if |hostname| ends with either ".local" or ".local.". -bool ResemblesMulticastDNSName(const std::string& hostname) { - DCHECK(!hostname.empty()); - const char kSuffix[] = ".local."; - const size_t kSuffixLen = sizeof(kSuffix) - 1; - const size_t kSuffixLenTrimmed = kSuffixLen - 1; - if (hostname[hostname.size() - 1] == '.') { - return hostname.size() > kSuffixLen && - !hostname.compare(hostname.size() - kSuffixLen, kSuffixLen, kSuffix); - } - return hostname.size() > kSuffixLenTrimmed && - !hostname.compare(hostname.size() - kSuffixLenTrimmed, kSuffixLenTrimmed, - kSuffix, kSuffixLenTrimmed); -} - -// Provide a common macro to simplify code and readability. We must use a -// macro as the underlying HISTOGRAM macro creates static variables. -#define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ - base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100) - -// A macro to simplify code and readability. -#define DNS_HISTOGRAM_BY_PRIORITY(basename, priority, time) \ - do { \ - switch (priority) { \ - case HIGHEST: DNS_HISTOGRAM(basename "_HIGHEST", time); break; \ - case MEDIUM: DNS_HISTOGRAM(basename "_MEDIUM", time); break; \ - case LOW: DNS_HISTOGRAM(basename "_LOW", time); break; \ - case LOWEST: DNS_HISTOGRAM(basename "_LOWEST", time); break; \ - case IDLE: DNS_HISTOGRAM(basename "_IDLE", time); break; \ - default: NOTREACHED(); break; \ - } \ - DNS_HISTOGRAM(basename, time); \ - } while (0) - -// Record time from Request creation until a valid DNS response. -void RecordTotalTime(bool had_dns_config, - bool speculative, - base::TimeDelta duration) { - if (had_dns_config) { - if (speculative) { - DNS_HISTOGRAM("AsyncDNS.TotalTime_speculative", duration); - } else { - DNS_HISTOGRAM("AsyncDNS.TotalTime", duration); - } - } else { - if (speculative) { - DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); - } else { - DNS_HISTOGRAM("DNS.TotalTime", duration); - } - } -} - -void RecordTTL(base::TimeDelta ttl) { - UMA_HISTOGRAM_CUSTOM_TIMES("AsyncDNS.TTL", ttl, - base::TimeDelta::FromSeconds(1), - base::TimeDelta::FromDays(1), 100); -} - -//----------------------------------------------------------------------------- - -// Wraps call to SystemHostResolverProc as an instance of HostResolverProc. -// TODO(szym): This should probably be declared in host_resolver_proc.h. -class CallSystemHostResolverProc : public HostResolverProc { - public: - CallSystemHostResolverProc() : HostResolverProc(NULL) {} - virtual int Resolve(const std::string& hostname, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addr_list, - int* os_error) OVERRIDE { - return SystemHostResolverProc(hostname, - address_family, - host_resolver_flags, - addr_list, - os_error); - } - - protected: - virtual ~CallSystemHostResolverProc() {} -}; - -AddressList EnsurePortOnAddressList(const AddressList& list, uint16 port) { - if (list.empty() || list.front().port() == port) - return list; - return AddressList::CopyWithPort(list, port); -} - -// Creates NetLog parameters when the resolve failed. -base::Value* NetLogProcTaskFailedCallback(uint32 attempt_number, - int net_error, - int os_error, - NetLog::LogLevel /* log_level */) { - DictionaryValue* dict = new DictionaryValue(); - if (attempt_number) - dict->SetInteger("attempt_number", attempt_number); - - dict->SetInteger("net_error", net_error); - - if (os_error) { - dict->SetInteger("os_error", os_error); -#if defined(OS_POSIX) - dict->SetString("os_error_string", gai_strerror(os_error)); -#elif defined(OS_WIN) - // Map the error code to a human-readable string. - LPWSTR error_string = NULL; - int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - 0, // Use the internal message table. - os_error, - 0, // Use default language. - (LPWSTR)&error_string, - 0, // Buffer size. - 0); // Arguments (unused). - dict->SetString("os_error_string", WideToUTF8(error_string)); - LocalFree(error_string); -#endif - } - - return dict; -} - -// Creates NetLog parameters when the DnsTask failed. -base::Value* NetLogDnsTaskFailedCallback(int net_error, - int dns_error, - NetLog::LogLevel /* log_level */) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("net_error", net_error); - if (dns_error) - dict->SetInteger("dns_error", dns_error); - return dict; -}; - -// Creates NetLog parameters containing the information in a RequestInfo object, -// along with the associated NetLog::Source. -base::Value* NetLogRequestInfoCallback(const NetLog::Source& source, - const HostResolver::RequestInfo* info, - NetLog::LogLevel /* log_level */) { - DictionaryValue* dict = new DictionaryValue(); - source.AddToEventParameters(dict); - - dict->SetString("host", info->host_port_pair().ToString()); - dict->SetInteger("address_family", - static_cast(info->address_family())); - dict->SetBoolean("allow_cached_response", info->allow_cached_response()); - dict->SetBoolean("is_speculative", info->is_speculative()); - dict->SetInteger("priority", info->priority()); - return dict; -} - -// Creates NetLog parameters for the creation of a HostResolverImpl::Job. -base::Value* NetLogJobCreationCallback(const NetLog::Source& source, - const std::string* host, - NetLog::LogLevel /* log_level */) { - DictionaryValue* dict = new DictionaryValue(); - source.AddToEventParameters(dict); - dict->SetString("host", *host); - return dict; -} - -// Creates NetLog parameters for HOST_RESOLVER_IMPL_JOB_ATTACH/DETACH events. -base::Value* NetLogJobAttachCallback(const NetLog::Source& source, - RequestPriority priority, - NetLog::LogLevel /* log_level */) { - DictionaryValue* dict = new DictionaryValue(); - source.AddToEventParameters(dict); - dict->SetInteger("priority", priority); - return dict; -} - -// Creates NetLog parameters for the DNS_CONFIG_CHANGED event. -base::Value* NetLogDnsConfigCallback(const DnsConfig* config, - NetLog::LogLevel /* log_level */) { - return config->ToValue(); -} - -// The logging routines are defined here because some requests are resolved -// without a Request object. - -// Logs when a request has just been started. -void LogStartRequest(const BoundNetLog& source_net_log, - const BoundNetLog& request_net_log, - const HostResolver::RequestInfo& info) { - source_net_log.BeginEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL, - request_net_log.source().ToEventParametersCallback()); - - request_net_log.BeginEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, - base::Bind(&NetLogRequestInfoCallback, source_net_log.source(), &info)); -} - -// Logs when a request has just completed (before its callback is run). -void LogFinishRequest(const BoundNetLog& source_net_log, - const BoundNetLog& request_net_log, - const HostResolver::RequestInfo& info, - int net_error) { - request_net_log.EndEventWithNetErrorCode( - NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, net_error); - source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); -} - -// Logs when a request has been cancelled. -void LogCancelRequest(const BoundNetLog& source_net_log, - const BoundNetLog& request_net_log, - const HostResolverImpl::RequestInfo& info) { - request_net_log.AddEvent(NetLog::TYPE_CANCELLED); - request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST); - source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); -} - -//----------------------------------------------------------------------------- - -// Keeps track of the highest priority. -class PriorityTracker { - public: - explicit PriorityTracker(RequestPriority initial_priority) - : highest_priority_(initial_priority), total_count_(0) { - memset(counts_, 0, sizeof(counts_)); - } - - RequestPriority highest_priority() const { - return highest_priority_; - } - - size_t total_count() const { - return total_count_; - } - - void Add(RequestPriority req_priority) { - ++total_count_; - ++counts_[req_priority]; - if (highest_priority_ < req_priority) - highest_priority_ = req_priority; - } - - void Remove(RequestPriority req_priority) { - DCHECK_GT(total_count_, 0u); - DCHECK_GT(counts_[req_priority], 0u); - --total_count_; - --counts_[req_priority]; - size_t i; - for (i = highest_priority_; i > MINIMUM_PRIORITY && !counts_[i]; --i); - highest_priority_ = static_cast(i); - - // In absence of requests, default to MINIMUM_PRIORITY. - if (total_count_ == 0) - DCHECK_EQ(MINIMUM_PRIORITY, highest_priority_); - } - - private: - RequestPriority highest_priority_; - size_t total_count_; - size_t counts_[NUM_PRIORITIES]; -}; - -} // namespace - -//----------------------------------------------------------------------------- - -// Holds the data for a request that could not be completed synchronously. -// It is owned by a Job. Canceled Requests are only marked as canceled rather -// than removed from the Job's |requests_| list. -class HostResolverImpl::Request { - public: - Request(const BoundNetLog& source_net_log, - const BoundNetLog& request_net_log, - const RequestInfo& info, - const CompletionCallback& callback, - AddressList* addresses) - : source_net_log_(source_net_log), - request_net_log_(request_net_log), - info_(info), - job_(NULL), - callback_(callback), - addresses_(addresses), - request_time_(base::TimeTicks::Now()) { - } - - // Mark the request as canceled. - void MarkAsCanceled() { - job_ = NULL; - addresses_ = NULL; - callback_.Reset(); - } - - bool was_canceled() const { - return callback_.is_null(); - } - - void set_job(Job* job) { - DCHECK(job); - // Identify which job the request is waiting on. - job_ = job; - } - - // Prepare final AddressList and call completion callback. - void OnComplete(int error, const AddressList& addr_list) { - DCHECK(!was_canceled()); - if (error == OK) - *addresses_ = EnsurePortOnAddressList(addr_list, info_.port()); - CompletionCallback callback = callback_; - MarkAsCanceled(); - callback.Run(error); - } - - Job* job() const { - return job_; - } - - // NetLog for the source, passed in HostResolver::Resolve. - const BoundNetLog& source_net_log() { - return source_net_log_; - } - - // NetLog for this request. - const BoundNetLog& request_net_log() { - return request_net_log_; - } - - const RequestInfo& info() const { - return info_; - } - - base::TimeTicks request_time() const { - return request_time_; - } - - private: - BoundNetLog source_net_log_; - BoundNetLog request_net_log_; - - // The request info that started the request. - RequestInfo info_; - - // The resolve job 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_; - - const base::TimeTicks request_time_; - - DISALLOW_COPY_AND_ASSIGN(Request); -}; - -//------------------------------------------------------------------------------ - -// Calls HostResolverProc on the WorkerPool. Performs retries if necessary. -// -// Whenever we try to resolve the host, we post a delayed task to check if host -// resolution (OnLookupComplete) is completed or not. If the original attempt -// hasn't completed, then we start another attempt for host resolution. We take -// the results from the first attempt that finishes and ignore the results from -// all other attempts. -// -// TODO(szym): Move to separate source file for testing and mocking. -// -class HostResolverImpl::ProcTask - : public base::RefCountedThreadSafe { - public: - typedef base::Callback Callback; - - ProcTask(const Key& key, - const ProcTaskParams& params, - const Callback& callback, - const BoundNetLog& job_net_log) - : key_(key), - params_(params), - callback_(callback), - origin_loop_(base::MessageLoopProxy::current()), - attempt_number_(0), - completed_attempt_number_(0), - completed_attempt_error_(ERR_UNEXPECTED), - had_non_speculative_request_(false), - net_log_(job_net_log) { - if (!params_.resolver_proc) - params_.resolver_proc = HostResolverProc::GetDefault(); - // If default is unset, use the system proc. - if (!params_.resolver_proc) - params_.resolver_proc = new CallSystemHostResolverProc(); - } - - void Start() { - DCHECK(origin_loop_->BelongsToCurrentThread()); - net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); - StartLookupAttempt(); - } - - // Cancels this ProcTask. It will be orphaned. Any outstanding resolve - // attempts running on worker threads will continue running. Only once all the - // attempts complete will the final reference to this ProcTask be released. - void Cancel() { - DCHECK(origin_loop_->BelongsToCurrentThread()); - - if (was_canceled() || was_completed()) - return; - - callback_.Reset(); - net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); - } - - void set_had_non_speculative_request() { - DCHECK(origin_loop_->BelongsToCurrentThread()); - had_non_speculative_request_ = true; - } - - bool was_canceled() const { - DCHECK(origin_loop_->BelongsToCurrentThread()); - return callback_.is_null(); - } - - bool was_completed() const { - DCHECK(origin_loop_->BelongsToCurrentThread()); - return completed_attempt_number_ > 0; - } - - private: - friend class base::RefCountedThreadSafe; - ~ProcTask() {} - - void StartLookupAttempt() { - DCHECK(origin_loop_->BelongsToCurrentThread()); - base::TimeTicks start_time = base::TimeTicks::Now(); - ++attempt_number_; - // Dispatch the lookup attempt to a worker thread. - if (!base::WorkerPool::PostTask( - FROM_HERE, - base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), - 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). - origin_loop_->PostTask( - FROM_HERE, - base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), - start_time, attempt_number_, ERR_UNEXPECTED, 0)); - return; - } - - net_log_.AddEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, - NetLog::IntegerCallback("attempt_number", attempt_number_)); - - // If we don't get the results within a given time, RetryIfNotComplete - // will start a new attempt on a different worker thread if none of our - // outstanding attempts have completed yet. - if (attempt_number_ <= params_.max_retry_attempts) { - origin_loop_->PostDelayedTask( - FROM_HERE, - base::Bind(&ProcTask::RetryIfNotComplete, this), - params_.unresponsive_delay); - } - } - - // WARNING: This code runs inside a worker pool. The shutdown code cannot - // wait for it to finish, so we must be very careful here about using other - // objects (like MessageLoops, Singletons, etc). During shutdown these objects - // may no longer exist. Multiple DoLookups() could be running in parallel, so - // any state inside of |this| must not mutate . - void DoLookup(const base::TimeTicks& start_time, - const uint32 attempt_number) { - AddressList results; - int os_error = 0; - // Running on the worker thread - int error = params_.resolver_proc->Resolve(key_.hostname, - key_.address_family, - key_.host_resolver_flags, - &results, - &os_error); - - origin_loop_->PostTask( - FROM_HERE, - base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, - attempt_number, error, os_error)); - } - - // Makes next attempt if DoLookup() has not finished (runs on origin thread). - void RetryIfNotComplete() { - DCHECK(origin_loop_->BelongsToCurrentThread()); - - if (was_completed() || was_canceled()) - return; - - params_.unresponsive_delay *= params_.retry_factor; - StartLookupAttempt(); - } - - // Callback for when DoLookup() completes (runs on origin thread). - void OnLookupComplete(const AddressList& results, - const base::TimeTicks& start_time, - const uint32 attempt_number, - int error, - const int os_error) { - DCHECK(origin_loop_->BelongsToCurrentThread()); - DCHECK(error || !results.empty()); - - bool was_retry_attempt = attempt_number > 1; - - // Ideally the following code would be part of host_resolver_proc.cc, - // however it isn't safe to call NetworkChangeNotifier from worker threads. - // So we do it here on the IO thread instead. - if (error != OK && NetworkChangeNotifier::IsOffline()) - error = ERR_INTERNET_DISCONNECTED; - - // If this is the first attempt that is finishing later, then record data - // for the first attempt. Won't contaminate with retry attempt's data. - if (!was_retry_attempt) - RecordPerformanceHistograms(start_time, error, os_error); - - RecordAttemptHistograms(start_time, attempt_number, error, os_error); - - if (was_canceled()) - return; - - NetLog::ParametersCallback net_log_callback; - if (error != OK) { - net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, - attempt_number, - error, - os_error); - } else { - net_log_callback = NetLog::IntegerCallback("attempt_number", - attempt_number); - } - net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, - net_log_callback); - - if (was_completed()) - return; - - // Copy the results from the first worker thread that resolves the host. - results_ = results; - completed_attempt_number_ = attempt_number; - completed_attempt_error_ = error; - - if (was_retry_attempt) { - // If retry attempt finishes before 1st attempt, then get stats on how - // much time is saved by having spawned an extra attempt. - retry_attempt_finished_time_ = base::TimeTicks::Now(); - } - - if (error != OK) { - net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, - 0, error, os_error); - } else { - net_log_callback = results_.CreateNetLogCallback(); - } - net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, - net_log_callback); - - callback_.Run(error, results_); - } - - void RecordPerformanceHistograms(const base::TimeTicks& start_time, - const int error, - const int os_error) const { - DCHECK(origin_loop_->BelongsToCurrentThread()); - enum Category { // Used in HISTOGRAM_ENUMERATION. - RESOLVE_SUCCESS, - RESOLVE_FAIL, - RESOLVE_SPECULATIVE_SUCCESS, - RESOLVE_SPECULATIVE_FAIL, - RESOLVE_MAX, // Bounding value. - }; - int category = RESOLVE_MAX; // Illegal value for later DCHECK only. - - base::TimeDelta duration = base::TimeTicks::Now() - start_time; - if (error == OK) { - if (had_non_speculative_request_) { - category = RESOLVE_SUCCESS; - DNS_HISTOGRAM("DNS.ResolveSuccess", duration); - } else { - category = RESOLVE_SPECULATIVE_SUCCESS; - DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration); - } - - // Log DNS lookups based on |address_family|. This will help us determine - // if IPv4 or IPv4/6 lookups are faster or slower. - switch(key_.address_family) { - case ADDRESS_FAMILY_IPV4: - DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV4", duration); - break; - case ADDRESS_FAMILY_IPV6: - DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV6", duration); - break; - case ADDRESS_FAMILY_UNSPECIFIED: - DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_UNSPEC", duration); - break; - } - } else { - if (had_non_speculative_request_) { - category = RESOLVE_FAIL; - DNS_HISTOGRAM("DNS.ResolveFail", duration); - } else { - category = RESOLVE_SPECULATIVE_FAIL; - DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration); - } - // Log DNS lookups based on |address_family|. This will help us determine - // if IPv4 or IPv4/6 lookups are faster or slower. - switch(key_.address_family) { - case ADDRESS_FAMILY_IPV4: - DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV4", duration); - break; - case ADDRESS_FAMILY_IPV6: - DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV6", duration); - break; - case ADDRESS_FAMILY_UNSPECIFIED: - DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_UNSPEC", duration); - break; - } - UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName, - std::abs(os_error), - GetAllGetAddrinfoOSErrors()); - } - DCHECK_LT(category, static_cast(RESOLVE_MAX)); // Be sure it was set. - - UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX); - - static const bool show_parallelism_experiment_histograms = - base::FieldTrialList::TrialExists("DnsParallelism"); - if (show_parallelism_experiment_histograms) { - UMA_HISTOGRAM_ENUMERATION( - base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsParallelism"), - category, RESOLVE_MAX); - if (RESOLVE_SUCCESS == category) { - DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess", - "DnsParallelism"), duration); - } - } - } - - void RecordAttemptHistograms(const base::TimeTicks& start_time, - const uint32 attempt_number, - const int error, - const int os_error) const { - DCHECK(origin_loop_->BelongsToCurrentThread()); - bool first_attempt_to_complete = - completed_attempt_number_ == attempt_number; - bool is_first_attempt = (attempt_number == 1); - - if (first_attempt_to_complete) { - // If this was first attempt to complete, then record the resolution - // status of the attempt. - if (completed_attempt_error_ == OK) { - UMA_HISTOGRAM_ENUMERATION( - "DNS.AttemptFirstSuccess", attempt_number, 100); - } else { - UMA_HISTOGRAM_ENUMERATION( - "DNS.AttemptFirstFailure", attempt_number, 100); - } - } - - if (error == OK) - UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100); - else - UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100); - - // If first attempt didn't finish before retry attempt, then calculate stats - // on how much time is saved by having spawned an extra attempt. - if (!first_attempt_to_complete && is_first_attempt && !was_canceled()) { - DNS_HISTOGRAM("DNS.AttemptTimeSavedByRetry", - base::TimeTicks::Now() - retry_attempt_finished_time_); - } - - if (was_canceled() || !first_attempt_to_complete) { - // Count those attempts which completed after the job was already canceled - // OR after the job was already completed by an earlier attempt (so in - // effect). - UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100); - - // Record if job is canceled. - if (was_canceled()) - UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); - } - - base::TimeDelta duration = base::TimeTicks::Now() - start_time; - if (error == OK) - DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); - else - DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); - } - - // Set on the origin thread, read on the worker thread. - Key key_; - - // Holds 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. - ProcTaskParams params_; - - // The listener to the results of this ProcTask. - Callback callback_; - - // Used to post ourselves onto the origin thread. - scoped_refptr origin_loop_; - - // Keeps track of the number of attempts we have made so far to resolve the - // host. Whenever we start an attempt to resolve the host, we increase this - // number. - uint32 attempt_number_; - - // The index of the attempt which finished first (or 0 if the job is still in - // progress). - uint32 completed_attempt_number_; - - // The result (a net error code) from the first attempt to complete. - int completed_attempt_error_; - - // The time when retry attempt was finished. - base::TimeTicks retry_attempt_finished_time_; - - // True if a non-speculative request was ever attached to this job - // (regardless of whether or not it was later canceled. - // This boolean is used for histogramming the duration of jobs used to - // service non-speculative requests. - bool had_non_speculative_request_; - - AddressList results_; - - BoundNetLog net_log_; - - DISALLOW_COPY_AND_ASSIGN(ProcTask); -}; - -//----------------------------------------------------------------------------- - -// Wraps a call to TestIPv6Support to be executed on the WorkerPool as it takes -// 40-100ms. -class HostResolverImpl::IPv6ProbeJob { - public: - IPv6ProbeJob(const base::WeakPtr& resolver, NetLog* net_log) - : resolver_(resolver), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_IPV6_PROBE_JOB)), - result_(false, IPV6_SUPPORT_MAX, OK) { - DCHECK(resolver); - net_log_.BeginEvent(NetLog::TYPE_IPV6_PROBE_RUNNING); - const bool kIsSlow = true; - base::WorkerPool::PostTaskAndReply( - FROM_HERE, - base::Bind(&IPv6ProbeJob::DoProbe, base::Unretained(this)), - base::Bind(&IPv6ProbeJob::OnProbeComplete, base::Owned(this)), - kIsSlow); - } - - virtual ~IPv6ProbeJob() {} - - private: - // Runs on worker thread. - void DoProbe() { - result_ = TestIPv6Support(); - } - - void OnProbeComplete() { - net_log_.EndEvent(NetLog::TYPE_IPV6_PROBE_RUNNING, - base::Bind(&IPv6SupportResult::ToNetLogValue, - base::Unretained(&result_))); - if (!resolver_) - return; - resolver_->IPv6ProbeSetDefaultAddressFamily( - result_.ipv6_supported ? ADDRESS_FAMILY_UNSPECIFIED - : ADDRESS_FAMILY_IPV4); - } - - // Used/set only on origin thread. - base::WeakPtr resolver_; - - BoundNetLog net_log_; - - IPv6SupportResult result_; - - DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); -}; - -// Wraps a call to HaveOnlyLoopbackAddresses to be executed on the WorkerPool as -// it takes 40-100ms and should not block initialization. -class HostResolverImpl::LoopbackProbeJob { - public: - explicit LoopbackProbeJob(const base::WeakPtr& resolver) - : resolver_(resolver), - result_(false) { - DCHECK(resolver); - const bool kIsSlow = true; - base::WorkerPool::PostTaskAndReply( - FROM_HERE, - base::Bind(&LoopbackProbeJob::DoProbe, base::Unretained(this)), - base::Bind(&LoopbackProbeJob::OnProbeComplete, base::Owned(this)), - kIsSlow); - } - - virtual ~LoopbackProbeJob() {} - - private: - // Runs on worker thread. - void DoProbe() { - result_ = HaveOnlyLoopbackAddresses(); - } - - void OnProbeComplete() { - if (!resolver_) - return; - resolver_->SetHaveOnlyLoopbackAddresses(result_); - } - - // Used/set only on origin thread. - base::WeakPtr resolver_; - - bool result_; - - DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); -}; - -//----------------------------------------------------------------------------- - -// Resolves the hostname using DnsTransaction. -// TODO(szym): This could be moved to separate source file as well. -class HostResolverImpl::DnsTask : public base::SupportsWeakPtr { - public: - typedef base::Callback Callback; - - DnsTask(DnsClient* client, - const Key& key, - const Callback& callback, - const BoundNetLog& job_net_log) - : client_(client), - family_(key.address_family), - callback_(callback), - net_log_(job_net_log) { - DCHECK(client); - DCHECK(!callback.is_null()); - - // If unspecified, do IPv4 first, because suffix search will be faster. - uint16 qtype = (family_ == ADDRESS_FAMILY_IPV6) ? - dns_protocol::kTypeAAAA : - dns_protocol::kTypeA; - transaction_ = client_->GetTransactionFactory()->CreateTransaction( - key.hostname, - qtype, - base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), - true /* first_query */, base::TimeTicks::Now()), - net_log_); - } - - int Start() { - net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK); - return transaction_->Start(); - } - - private: - void OnTransactionComplete(bool first_query, - const base::TimeTicks& start_time, - DnsTransaction* transaction, - int net_error, - const DnsResponse* response) { - DCHECK(transaction); - base::TimeDelta duration = base::TimeTicks::Now() - start_time; - // Run |callback_| last since the owning Job will then delete this DnsTask. - if (net_error != OK) { - DNS_HISTOGRAM("AsyncDNS.TransactionFailure", duration); - OnFailure(net_error, DnsResponse::DNS_PARSE_OK); - return; - } - - CHECK(response); - DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", duration); - switch (transaction->GetType()) { - case dns_protocol::kTypeA: - DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_A", duration); - break; - case dns_protocol::kTypeAAAA: - DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_AAAA", duration); - break; - } - AddressList addr_list; - base::TimeDelta ttl; - DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); - UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", - result, - DnsResponse::DNS_PARSE_RESULT_MAX); - if (result != DnsResponse::DNS_PARSE_OK) { - // Fail even if the other query succeeds. - OnFailure(ERR_DNS_MALFORMED_RESPONSE, result); - return; - } - - bool needs_sort = false; - if (first_query) { - DCHECK(client_->GetConfig()) << - "Transaction should have been aborted when config changed!"; - if (family_ == ADDRESS_FAMILY_IPV6) { - needs_sort = (addr_list.size() > 1); - } else if (family_ == ADDRESS_FAMILY_UNSPECIFIED) { - first_addr_list_ = addr_list; - first_ttl_ = ttl; - // Use fully-qualified domain name to avoid search. - transaction_ = client_->GetTransactionFactory()->CreateTransaction( - response->GetDottedName() + ".", - dns_protocol::kTypeAAAA, - base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), - false /* first_query */, base::TimeTicks::Now()), - net_log_); - net_error = transaction_->Start(); - if (net_error != ERR_IO_PENDING) - OnFailure(net_error, DnsResponse::DNS_PARSE_OK); - return; - } - } else { - DCHECK_EQ(ADDRESS_FAMILY_UNSPECIFIED, family_); - bool has_ipv6_addresses = !addr_list.empty(); - if (!first_addr_list_.empty()) { - ttl = std::min(ttl, first_ttl_); - // Place IPv4 addresses after IPv6. - addr_list.insert(addr_list.end(), first_addr_list_.begin(), - first_addr_list_.end()); - } - needs_sort = (has_ipv6_addresses && addr_list.size() > 1); - } - - if (addr_list.empty()) { - // TODO(szym): Don't fallback to ProcTask in this case. - OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); - return; - } - - if (needs_sort) { - // Sort could complete synchronously. - client_->GetAddressSorter()->Sort( - addr_list, - base::Bind(&DnsTask::OnSortComplete, - AsWeakPtr(), - base::TimeTicks::Now(), - ttl)); - } else { - OnSuccess(addr_list, ttl); - } - } - - void OnSortComplete(base::TimeTicks start_time, - base::TimeDelta ttl, - bool success, - const AddressList& addr_list) { - if (!success) { - DNS_HISTOGRAM("AsyncDNS.SortFailure", - base::TimeTicks::Now() - start_time); - OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK); - return; - } - - DNS_HISTOGRAM("AsyncDNS.SortSuccess", - base::TimeTicks::Now() - start_time); - - // AddressSorter prunes unusable destinations. - if (addr_list.empty()) { - LOG(WARNING) << "Address list empty after RFC3484 sort"; - OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); - return; - } - - OnSuccess(addr_list, ttl); - } - - void OnFailure(int net_error, DnsResponse::Result result) { - DCHECK_NE(OK, net_error); - net_log_.EndEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, - base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); - callback_.Run(net_error, AddressList(), base::TimeDelta()); - } - - void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) { - net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, - addr_list.CreateNetLogCallback()); - callback_.Run(OK, addr_list, ttl); - } - - DnsClient* client_; - AddressFamily family_; - // The listener to the results of this DnsTask. - Callback callback_; - const BoundNetLog net_log_; - - scoped_ptr transaction_; - - // Results from the first transaction. Used only if |family_| is unspecified. - AddressList first_addr_list_; - base::TimeDelta first_ttl_; - - DISALLOW_COPY_AND_ASSIGN(DnsTask); -}; - -//----------------------------------------------------------------------------- - -// Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. -class HostResolverImpl::Job : public PrioritizedDispatcher::Job { - public: - // Creates new job for |key| where |request_net_log| is bound to the - // request that spawned it. - Job(const base::WeakPtr& resolver, - const Key& key, - RequestPriority priority, - const BoundNetLog& request_net_log) - : resolver_(resolver), - key_(key), - priority_tracker_(priority), - had_non_speculative_request_(false), - had_dns_config_(false), - dns_task_error_(OK), - creation_time_(base::TimeTicks::Now()), - priority_change_time_(creation_time_), - net_log_(BoundNetLog::Make(request_net_log.net_log(), - NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { - request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB); - - net_log_.BeginEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, - base::Bind(&NetLogJobCreationCallback, - request_net_log.source(), - &key_.hostname)); - } - - virtual ~Job() { - if (is_running()) { - // |resolver_| was destroyed with this Job still in flight. - // Clean-up, record in the log, but don't run any callbacks. - if (is_proc_running()) { - proc_task_->Cancel(); - proc_task_ = NULL; - } - // Clean up now for nice NetLog. - dns_task_.reset(NULL); - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, - ERR_ABORTED); - } else if (is_queued()) { - // |resolver_| was destroyed without running this Job. - // TODO(szym): is there any benefit in having this distinction? - net_log_.AddEvent(NetLog::TYPE_CANCELLED); - net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB); - } - // else CompleteRequests logged EndEvent. - - // Log any remaining Requests as cancelled. - for (RequestsList::const_iterator it = requests_.begin(); - it != requests_.end(); ++it) { - Request* req = *it; - if (req->was_canceled()) - continue; - DCHECK_EQ(this, req->job()); - LogCancelRequest(req->source_net_log(), req->request_net_log(), - req->info()); - } - } - - // Add this job to the dispatcher. - void Schedule() { - handle_ = resolver_->dispatcher_.Add(this, priority()); - } - - void AddRequest(scoped_ptr req) { - DCHECK_EQ(key_.hostname, req->info().hostname()); - - req->set_job(this); - priority_tracker_.Add(req->info().priority()); - - req->request_net_log().AddEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, - net_log_.source().ToEventParametersCallback()); - - net_log_.AddEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, - base::Bind(&NetLogJobAttachCallback, - req->request_net_log().source(), - priority())); - - // TODO(szym): Check if this is still needed. - if (!req->info().is_speculative()) { - had_non_speculative_request_ = true; - if (proc_task_) - proc_task_->set_had_non_speculative_request(); - } - - requests_.push_back(req.release()); - - UpdatePriority(); - } - - // Marks |req| as cancelled. If it was the last active Request, also finishes - // this Job, marking it as cancelled, and deletes it. - void CancelRequest(Request* req) { - DCHECK_EQ(key_.hostname, req->info().hostname()); - DCHECK(!req->was_canceled()); - - // Don't remove it from |requests_| just mark it canceled. - req->MarkAsCanceled(); - LogCancelRequest(req->source_net_log(), req->request_net_log(), - req->info()); - - priority_tracker_.Remove(req->info().priority()); - net_log_.AddEvent( - NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, - base::Bind(&NetLogJobAttachCallback, - req->request_net_log().source(), - priority())); - - if (num_active_requests() > 0) { - UpdatePriority(); - } else { - // If we were called from a Request's callback within CompleteRequests, - // that Request could not have been cancelled, so num_active_requests() - // could not be 0. Therefore, we are not in CompleteRequests(). - CompleteRequestsWithError(OK /* cancelled */); - } - } - - // Called from AbortAllInProgressJobs. Completes all requests and destroys - // the job. This currently assumes the abort is due to a network change. - void Abort() { - DCHECK(is_running()); - CompleteRequestsWithError(ERR_NETWORK_CHANGED); - } - - // If DnsTask present, abort it and fall back to ProcTask. - void AbortDnsTask() { - if (dns_task_) { - dns_task_.reset(); - dns_task_error_ = OK; - StartProcTask(); - } - } - - // Called by HostResolverImpl when this job is evicted due to queue overflow. - // Completes all requests and destroys the job. - void OnEvicted() { - DCHECK(!is_running()); - DCHECK(is_queued()); - handle_.Reset(); - - net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); - - // This signals to CompleteRequests that this job never ran. - CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); - } - - // Attempts to serve the job from HOSTS. Returns true if succeeded and - // this Job was destroyed. - bool ServeFromHosts() { - DCHECK_GT(num_active_requests(), 0u); - AddressList addr_list; - if (resolver_->ServeFromHosts(key(), - requests_.front()->info(), - &addr_list)) { - // This will destroy the Job. - CompleteRequests( - HostCache::Entry(OK, MakeAddressListForRequest(addr_list)), - base::TimeDelta()); - return true; - } - return false; - } - - const Key key() const { - return key_; - } - - bool is_queued() const { - return !handle_.is_null(); - } - - bool is_running() const { - return is_dns_running() || is_proc_running(); - } - - private: - void UpdatePriority() { - if (is_queued()) { - if (priority() != static_cast(handle_.priority())) - priority_change_time_ = base::TimeTicks::Now(); - handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); - } - } - - AddressList MakeAddressListForRequest(const AddressList& list) const { - if (requests_.empty()) - return list; - return AddressList::CopyWithPort(list, requests_.front()->info().port()); - } - - // PriorityDispatch::Job: - virtual void Start() OVERRIDE { - DCHECK(!is_running()); - handle_.Reset(); - - net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED); - - had_dns_config_ = resolver_->HaveDnsConfig(); - - base::TimeTicks now = base::TimeTicks::Now(); - base::TimeDelta queue_time = now - creation_time_; - base::TimeDelta queue_time_after_change = now - priority_change_time_; - - if (had_dns_config_) { - DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTime", priority(), - queue_time); - DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTimeAfterChange", priority(), - queue_time_after_change); - } else { - DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTime", priority(), queue_time); - DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTimeAfterChange", priority(), - queue_time_after_change); - } - - // Caution: Job::Start must not complete synchronously. - if (had_dns_config_ && !ResemblesMulticastDNSName(key_.hostname)) { - StartDnsTask(); - } else { - StartProcTask(); - } - } - - // TODO(szym): Since DnsTransaction does not consume threads, we can increase - // the limits on |dispatcher_|. But in order to keep the number of WorkerPool - // threads low, we will need to use an "inner" PrioritizedDispatcher with - // tighter limits. - void StartProcTask() { - DCHECK(!is_dns_running()); - proc_task_ = new ProcTask( - key_, - resolver_->proc_params_, - base::Bind(&Job::OnProcTaskComplete, base::Unretained(this), - base::TimeTicks::Now()), - net_log_); - - if (had_non_speculative_request_) - proc_task_->set_had_non_speculative_request(); - // Start() could be called from within Resolve(), hence it must NOT directly - // call OnProcTaskComplete, for example, on synchronous failure. - proc_task_->Start(); - } - - // Called by ProcTask when it completes. - void OnProcTaskComplete(base::TimeTicks start_time, - int net_error, - const AddressList& addr_list) { - DCHECK(is_proc_running()); - - if (!resolver_->resolved_known_ipv6_hostname_ && - net_error == OK && - key_.address_family == ADDRESS_FAMILY_UNSPECIFIED) { - if (key_.hostname == "www.google.com") { - resolver_->resolved_known_ipv6_hostname_ = true; - bool got_ipv6_address = false; - for (size_t i = 0; i < addr_list.size(); ++i) { - if (addr_list[i].GetFamily() == ADDRESS_FAMILY_IPV6) - got_ipv6_address = true; - } - UMA_HISTOGRAM_BOOLEAN("Net.UnspecResolvedIPv6", got_ipv6_address); - } - } - - if (dns_task_error_ != OK) { - base::TimeDelta duration = base::TimeTicks::Now() - start_time; - if (net_error == OK) { - DNS_HISTOGRAM("AsyncDNS.FallbackSuccess", duration); - if ((dns_task_error_ == ERR_NAME_NOT_RESOLVED) && - ResemblesNetBIOSName(key_.hostname)) { - UmaAsyncDnsResolveStatus(RESOLVE_STATUS_SUSPECT_NETBIOS); - } else { - UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); - } - UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", - std::abs(dns_task_error_), - GetAllErrorCodesForUma()); - resolver_->OnDnsTaskResolve(dns_task_error_); - } else { - DNS_HISTOGRAM("AsyncDNS.FallbackFail", duration); - UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); - } - } - - base::TimeDelta ttl = - base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds); - if (net_error == OK) - ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); - - // Don't store the |ttl| in cache since it's not obtained from the server. - CompleteRequests( - HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)), - ttl); - } - - void StartDnsTask() { - DCHECK(resolver_->HaveDnsConfig()); - dns_task_.reset(new DnsTask( - resolver_->dns_client_.get(), - key_, - base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this), - base::TimeTicks::Now()), - net_log_)); - - int rv = dns_task_->Start(); - if (rv != ERR_IO_PENDING) { - DCHECK_NE(OK, rv); - dns_task_error_ = rv; - dns_task_.reset(); - StartProcTask(); - } - } - - // Called by DnsTask when it completes. - void OnDnsTaskComplete(base::TimeTicks start_time, - int net_error, - const AddressList& addr_list, - base::TimeDelta ttl) { - DCHECK(is_dns_running()); - - base::TimeDelta duration = base::TimeTicks::Now() - start_time; - if (net_error != OK) { - DNS_HISTOGRAM("AsyncDNS.ResolveFail", duration); - - dns_task_error_ = net_error; - dns_task_.reset(); - - // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. - // http://crbug.com/117655 - - // TODO(szym): Some net errors indicate lack of connectivity. Starting - // ProcTask in that case is a waste of time. - StartProcTask(); - return; - } - DNS_HISTOGRAM("AsyncDNS.ResolveSuccess", duration); - // Log DNS lookups based on |address_family|. - switch(key_.address_family) { - case ADDRESS_FAMILY_IPV4: - DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV4", duration); - break; - case ADDRESS_FAMILY_IPV6: - DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV6", duration); - break; - case ADDRESS_FAMILY_UNSPECIFIED: - DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_UNSPEC", duration); - break; - } - - UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); - RecordTTL(ttl); - - resolver_->OnDnsTaskResolve(OK); - - base::TimeDelta bounded_ttl = - std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds)); - - CompleteRequests( - HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl), - bounded_ttl); - } - - // Performs Job's last rites. Completes all Requests. Deletes this. - void CompleteRequests(const HostCache::Entry& entry, - base::TimeDelta ttl) { - CHECK(resolver_); - - // This job must be removed from resolver's |jobs_| now to make room for a - // new job with the same key in case one of the OnComplete callbacks decides - // to spawn one. Consequently, the job deletes itself when CompleteRequests - // is done. - scoped_ptr self_deleter(this); - - resolver_->RemoveJob(this); - - if (is_running()) { - DCHECK(!is_queued()); - if (is_proc_running()) { - proc_task_->Cancel(); - proc_task_ = NULL; - } - dns_task_.reset(); - - // Signal dispatcher that a slot has opened. - resolver_->dispatcher_.OnJobFinished(); - } else if (is_queued()) { - resolver_->dispatcher_.Cancel(handle_); - handle_.Reset(); - } - - if (num_active_requests() == 0) { - net_log_.AddEvent(NetLog::TYPE_CANCELLED); - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, - OK); - return; - } - - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, - entry.error); - - DCHECK(!requests_.empty()); - - if (entry.error == OK) { - // Record this histogram here, when we know the system has a valid DNS - // configuration. - UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", - resolver_->received_dns_config_); - } - - bool did_complete = (entry.error != ERR_NETWORK_CHANGED) && - (entry.error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); - if (did_complete) - resolver_->CacheResult(key_, entry, ttl); - - // Complete all of the requests that were attached to the job. - for (RequestsList::const_iterator it = requests_.begin(); - it != requests_.end(); ++it) { - Request* req = *it; - - if (req->was_canceled()) - continue; - - DCHECK_EQ(this, req->job()); - // Update the net log and notify registered observers. - LogFinishRequest(req->source_net_log(), req->request_net_log(), - req->info(), entry.error); - if (did_complete) { - // Record effective total time from creation to completion. - RecordTotalTime(had_dns_config_, req->info().is_speculative(), - base::TimeTicks::Now() - req->request_time()); - } - req->OnComplete(entry.error, entry.addrlist); - - // Check if the resolver was destroyed as a result of running the - // callback. If it was, we could continue, but we choose to bail. - if (!resolver_) - return; - } - } - - // Convenience wrapper for CompleteRequests in case of failure. - void CompleteRequestsWithError(int net_error) { - CompleteRequests(HostCache::Entry(net_error, AddressList()), - base::TimeDelta()); - } - - RequestPriority priority() const { - return priority_tracker_.highest_priority(); - } - - // Number of non-canceled requests in |requests_|. - size_t num_active_requests() const { - return priority_tracker_.total_count(); - } - - bool is_dns_running() const { - return dns_task_.get() != NULL; - } - - bool is_proc_running() const { - return proc_task_.get() != NULL; - } - - base::WeakPtr resolver_; - - Key key_; - - // Tracks the highest priority across |requests_|. - PriorityTracker priority_tracker_; - - bool had_non_speculative_request_; - - // Distinguishes measurements taken while DnsClient was fully configured. - bool had_dns_config_; - - // Result of DnsTask. - int dns_task_error_; - - const base::TimeTicks creation_time_; - base::TimeTicks priority_change_time_; - - BoundNetLog net_log_; - - // Resolves the host using a HostResolverProc. - scoped_refptr proc_task_; - - // Resolves the host using a DnsTransaction. - scoped_ptr dns_task_; - - // All Requests waiting for the result of this Job. Some can be canceled. - RequestsList requests_; - - // A handle used in |HostResolverImpl::dispatcher_|. - PrioritizedDispatcher::Handle handle_; -}; - -//----------------------------------------------------------------------------- - -HostResolverImpl::ProcTaskParams::ProcTaskParams( - HostResolverProc* resolver_proc, - size_t max_retry_attempts) - : resolver_proc(resolver_proc), - max_retry_attempts(max_retry_attempts), - unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), - retry_factor(2) { -} - -HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} - -HostResolverImpl::HostResolverImpl( - scoped_ptr cache, - const PrioritizedDispatcher::Limits& job_limits, - const ProcTaskParams& proc_params, - NetLog* net_log) - : cache_(cache.Pass()), - dispatcher_(job_limits), - max_queued_jobs_(job_limits.total_jobs * 100u), - proc_params_(proc_params), - net_log_(net_log), - default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), - weak_ptr_factory_(this), - probe_weak_ptr_factory_(this), - received_dns_config_(false), - num_dns_failures_(0), - ipv6_probe_monitoring_(false), - resolved_known_ipv6_hostname_(false), - additional_resolver_flags_(0) { - - DCHECK_GE(dispatcher_.num_priorities(), static_cast(NUM_PRIORITIES)); - - // Maximum of 4 retry attempts for host resolution. - static const size_t kDefaultMaxRetryAttempts = 4u; - - if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) - proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; - -#if defined(OS_WIN) - EnsureWinsockInit(); -#endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) - new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr()); -#endif - NetworkChangeNotifier::AddIPAddressObserver(this); - NetworkChangeNotifier::AddDNSObserver(this); -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ - !defined(OS_ANDROID) - EnsureDnsReloaderInit(); -#endif - - // TODO(szym): Remove when received_dns_config_ is removed, once - // http://crbug.com/137914 is resolved. - { - DnsConfig dns_config; - NetworkChangeNotifier::GetDnsConfig(&dns_config); - received_dns_config_ = dns_config.IsValid(); - } -} - -HostResolverImpl::~HostResolverImpl() { - // This will also cancel all outstanding requests. - STLDeleteValues(&jobs_); - - NetworkChangeNotifier::RemoveIPAddressObserver(this); - NetworkChangeNotifier::RemoveDNSObserver(this); -} - -void HostResolverImpl::SetMaxQueuedJobs(size_t value) { - DCHECK_EQ(0u, dispatcher_.num_queued_jobs()); - DCHECK_GT(value, 0u); - max_queued_jobs_ = value; -} - -int HostResolverImpl::Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& source_net_log) { - DCHECK(addresses); - DCHECK(CalledOnValidThread()); - DCHECK_EQ(false, callback.is_null()); - - // Make a log item for the request. - BoundNetLog request_net_log = BoundNetLog::Make(net_log_, - NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); - - LogStartRequest(source_net_log, request_net_log, info); - - // Build a key that identifies the request in the cache and in the - // outstanding jobs map. - Key key = GetEffectiveKeyForRequest(info); - - int rv = ResolveHelper(key, info, addresses, request_net_log); - if (rv != ERR_DNS_CACHE_MISS) { - LogFinishRequest(source_net_log, request_net_log, info, rv); - RecordTotalTime(HaveDnsConfig(), info.is_speculative(), base::TimeDelta()); - return rv; - } - - // Next we need to attach our request to a "job". This job is responsible for - // calling "getaddrinfo(hostname)" on a worker thread. - - JobMap::iterator jobit = jobs_.find(key); - Job* job; - if (jobit == jobs_.end()) { - job = new Job(weak_ptr_factory_.GetWeakPtr(), key, info.priority(), - request_net_log); - job->Schedule(); - - // Check for queue overflow. - if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { - Job* evicted = static_cast(dispatcher_.EvictOldestLowest()); - DCHECK(evicted); - evicted->OnEvicted(); // Deletes |evicted|. - if (evicted == job) { - rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; - LogFinishRequest(source_net_log, request_net_log, info, rv); - return rv; - } - } - jobs_.insert(jobit, std::make_pair(key, job)); - } else { - job = jobit->second; - } - - // Can't complete synchronously. Create and attach request. - scoped_ptr req(new Request(source_net_log, - request_net_log, - info, - callback, - addresses)); - if (out_req) - *out_req = reinterpret_cast(req.get()); - - job->AddRequest(req.Pass()); - // Completion happens during Job::CompleteRequests(). - return ERR_IO_PENDING; -} - -int HostResolverImpl::ResolveHelper(const Key& key, - const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& request_net_log) { - // The result of |getaddrinfo| for empty hosts is inconsistent across systems. - // On Windows it gives the default interface's address, whereas on Linux it - // gives an error. We will make it fail on all platforms for consistency. - if (info.hostname().empty() || info.hostname().size() > kMaxHostLength) - return ERR_NAME_NOT_RESOLVED; - - int net_error = ERR_UNEXPECTED; - if (ResolveAsIP(key, info, &net_error, addresses)) - return net_error; - if (ServeFromCache(key, info, &net_error, addresses)) { - request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT); - return net_error; - } - // TODO(szym): Do not do this if nsswitch.conf instructs not to. - // http://crbug.com/117655 - if (ServeFromHosts(key, info, addresses)) { - request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_HOSTS_HIT); - return OK; - } - return ERR_DNS_CACHE_MISS; -} - -int HostResolverImpl::ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& source_net_log) { - DCHECK(CalledOnValidThread()); - DCHECK(addresses); - - // Make a log item for the request. - BoundNetLog request_net_log = BoundNetLog::Make(net_log_, - NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); - - // Update the net log and notify registered observers. - LogStartRequest(source_net_log, request_net_log, info); - - Key key = GetEffectiveKeyForRequest(info); - - int rv = ResolveHelper(key, info, addresses, request_net_log); - LogFinishRequest(source_net_log, request_net_log, info, rv); - return rv; -} - -void HostResolverImpl::CancelRequest(RequestHandle req_handle) { - DCHECK(CalledOnValidThread()); - Request* req = reinterpret_cast(req_handle); - DCHECK(req); - Job* job = req->job(); - DCHECK(job); - job->CancelRequest(req); -} - -void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { - DCHECK(CalledOnValidThread()); - default_address_family_ = address_family; - ipv6_probe_monitoring_ = false; -} - -AddressFamily HostResolverImpl::GetDefaultAddressFamily() const { - return default_address_family_; -} - -void HostResolverImpl::ProbeIPv6Support() { - DCHECK(CalledOnValidThread()); - DCHECK(!ipv6_probe_monitoring_); - ipv6_probe_monitoring_ = true; - OnIPAddressChanged(); -} - -void HostResolverImpl::SetDnsClientEnabled(bool enabled) { - DCHECK(CalledOnValidThread()); -#if defined(ENABLE_BUILT_IN_DNS) - if (enabled && !dns_client_) { - SetDnsClient(DnsClient::CreateClient(net_log_)); - } else if (!enabled && dns_client_) { - SetDnsClient(scoped_ptr()); - } -#endif -} - -HostCache* HostResolverImpl::GetHostCache() { - return cache_.get(); -} - -base::Value* HostResolverImpl::GetDnsConfigAsValue() const { - // Check if async DNS is disabled. - if (!dns_client_.get()) - return NULL; - - // Check if async DNS is enabled, but we currently have no configuration - // for it. - const DnsConfig* dns_config = dns_client_->GetConfig(); - if (dns_config == NULL) - return new DictionaryValue(); - - return dns_config->ToValue(); -} - -bool HostResolverImpl::ResolveAsIP(const Key& key, - const RequestInfo& info, - int* net_error, - AddressList* addresses) { - DCHECK(addresses); - DCHECK(net_error); - IPAddressNumber ip_number; - if (!ParseIPLiteralToNumber(key.hostname, &ip_number)) - return false; - - DCHECK_EQ(key.host_resolver_flags & - ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6), - 0) << " Unhandled flag"; - bool ipv6_disabled = (default_address_family_ == ADDRESS_FAMILY_IPV4) && - !ipv6_probe_monitoring_; - *net_error = OK; - if ((ip_number.size() == kIPv6AddressSize) && ipv6_disabled) { - *net_error = ERR_NAME_NOT_RESOLVED; - } else { - *addresses = AddressList::CreateFromIPAddress(ip_number, info.port()); - if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME) - addresses->SetDefaultCanonicalName(); - } - return true; -} - -bool HostResolverImpl::ServeFromCache(const Key& key, - const RequestInfo& info, - int* net_error, - AddressList* addresses) { - DCHECK(addresses); - DCHECK(net_error); - if (!info.allow_cached_response() || !cache_.get()) - return false; - - const HostCache::Entry* cache_entry = cache_->Lookup( - key, base::TimeTicks::Now()); - if (!cache_entry) - return false; - - *net_error = cache_entry->error; - if (*net_error == OK) { - if (cache_entry->has_ttl()) - RecordTTL(cache_entry->ttl); - *addresses = EnsurePortOnAddressList(cache_entry->addrlist, info.port()); - } - return true; -} - -bool HostResolverImpl::ServeFromHosts(const Key& key, - const RequestInfo& info, - AddressList* addresses) { - DCHECK(addresses); - if (!HaveDnsConfig()) - return false; - - // HOSTS lookups are case-insensitive. - std::string hostname = StringToLowerASCII(key.hostname); - - // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations - // (glibc and c-ares) return the first matching line. We have more - // flexibility, but lose implicit ordering. - // TODO(szym) http://crbug.com/117850 - const DnsHosts& hosts = dns_client_->GetConfig()->hosts; - DnsHosts::const_iterator it = hosts.find( - DnsHostsKey(hostname, - key.address_family == ADDRESS_FAMILY_UNSPECIFIED ? - ADDRESS_FAMILY_IPV4 : key.address_family)); - - if (it == hosts.end()) { - if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED) - return false; - - it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); - if (it == hosts.end()) - return false; - } - - *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); - return true; -} - -void HostResolverImpl::CacheResult(const Key& key, - const HostCache::Entry& entry, - base::TimeDelta ttl) { - if (cache_.get()) - cache_->Set(key, entry, base::TimeTicks::Now(), ttl); -} - -void HostResolverImpl::RemoveJob(Job* job) { - DCHECK(job); - JobMap::iterator it = jobs_.find(job->key()); - if (it != jobs_.end() && it->second == job) - jobs_.erase(it); -} - -void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( - AddressFamily address_family) { - DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || - address_family == ADDRESS_FAMILY_IPV4); - if (!ipv6_probe_monitoring_) - return; - if (default_address_family_ != address_family) { - VLOG(1) << "IPv6Probe forced AddressFamily setting to " - << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ? - "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4"); - } - default_address_family_ = address_family; -} - -void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) { - if (result) { - additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; - } else { - additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; - } -} - -HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( - const RequestInfo& info) const { - HostResolverFlags effective_flags = - info.host_resolver_flags() | additional_resolver_flags_; - AddressFamily effective_address_family = info.address_family(); - if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED && - default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { - effective_address_family = default_address_family_; - if (ipv6_probe_monitoring_) - effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - } - return Key(info.hostname(), effective_address_family, effective_flags); -} - -void HostResolverImpl::AbortAllInProgressJobs() { - // In Abort, a Request callback could spawn new Jobs with matching keys, so - // first collect and remove all running jobs from |jobs_|. - ScopedVector jobs_to_abort; - for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { - Job* job = it->second; - if (job->is_running()) { - jobs_to_abort.push_back(job); - jobs_.erase(it++); - } else { - DCHECK(job->is_queued()); - ++it; - } - } - - // Check if no dispatcher slots leaked out. - DCHECK_EQ(dispatcher_.num_running_jobs(), jobs_to_abort.size()); - - // Life check to bail once |this| is deleted. - base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); - - // Then Abort them. - for (size_t i = 0; self && i < jobs_to_abort.size(); ++i) { - jobs_to_abort[i]->Abort(); - jobs_to_abort[i] = NULL; - } -} - -void HostResolverImpl::TryServingAllJobsFromHosts() { - if (!HaveDnsConfig()) - return; - - // TODO(szym): Do not do this if nsswitch.conf instructs not to. - // http://crbug.com/117655 - - // Life check to bail once |this| is deleted. - base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); - - for (JobMap::iterator it = jobs_.begin(); self && it != jobs_.end(); ) { - Job* job = it->second; - ++it; - // This could remove |job| from |jobs_|, but iterator will remain valid. - job->ServeFromHosts(); - } -} - -void HostResolverImpl::OnIPAddressChanged() { - resolved_known_ipv6_hostname_ = false; - // Abandon all ProbeJobs. - probe_weak_ptr_factory_.InvalidateWeakPtrs(); - if (cache_.get()) - cache_->clear(); - if (ipv6_probe_monitoring_) - new IPv6ProbeJob(probe_weak_ptr_factory_.GetWeakPtr(), net_log_); -#if defined(OS_POSIX) && !defined(OS_MACOSX) - new LoopbackProbeJob(probe_weak_ptr_factory_.GetWeakPtr()); -#endif - AbortAllInProgressJobs(); - // |this| may be deleted inside AbortAllInProgressJobs(). -} - -void HostResolverImpl::OnDNSChanged() { - DnsConfig dns_config; - NetworkChangeNotifier::GetDnsConfig(&dns_config); - if (net_log_) { - net_log_->AddGlobalEntry( - NetLog::TYPE_DNS_CONFIG_CHANGED, - base::Bind(&NetLogDnsConfigCallback, &dns_config)); - } - - // TODO(szym): Remove once http://crbug.com/137914 is resolved. - received_dns_config_ = dns_config.IsValid(); - - num_dns_failures_ = 0; - - // We want a new DnsSession in place, before we Abort running Jobs, so that - // the newly started jobs use the new config. - if (dns_client_.get()) { - dns_client_->SetConfig(dns_config); - if (dns_config.IsValid()) - UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); - } - - // If the DNS server has changed, existing cached info could be wrong so we - // have to drop our internal cache :( Note that OS level DNS caches, such - // as NSCD's cache should be dropped automatically by the OS when - // resolv.conf changes so we don't need to do anything to clear that cache. - if (cache_.get()) - cache_->clear(); - - // Life check to bail once |this| is deleted. - base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); - - // Existing jobs will have been sent to the original server so they need to - // be aborted. - AbortAllInProgressJobs(); - - // |this| may be deleted inside AbortAllInProgressJobs(). - if (self) - TryServingAllJobsFromHosts(); -} - -bool HostResolverImpl::HaveDnsConfig() const { - // Use DnsClient only if it's fully configured and there is no override by - // ScopedDefaultHostResolverProc. - // The alternative is to use NetworkChangeNotifier to override DnsConfig, - // but that would introduce construction order requirements for NCN and SDHRP. - return (dns_client_.get() != NULL) && - (dns_client_->GetConfig() != NULL) && - !(proc_params_.resolver_proc == NULL && - HostResolverProc::GetDefault() != NULL); -} - -void HostResolverImpl::OnDnsTaskResolve(int net_error) { - DCHECK(dns_client_); - if (net_error == OK) { - num_dns_failures_ = 0; - return; - } - ++num_dns_failures_; - if (num_dns_failures_ < kMaximumDnsFailures) - return; - // Disable DnsClient until the next DNS change. - for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) - it->second->AbortDnsTask(); - dns_client_->SetConfig(DnsConfig()); - UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.DnsClientDisabledReason", - std::abs(net_error), - GetAllErrorCodesForUma()); -} - -void HostResolverImpl::SetDnsClient(scoped_ptr dns_client) { - if (HaveDnsConfig()) { - for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) - it->second->AbortDnsTask(); - } - dns_client_ = dns_client.Pass(); - if (!dns_client_ || dns_client_->GetConfig() || - num_dns_failures_ >= kMaximumDnsFailures) { - return; - } - DnsConfig dns_config; - NetworkChangeNotifier::GetDnsConfig(&dns_config); - dns_client_->SetConfig(dns_config); - num_dns_failures_ = 0; - if (dns_config.IsValid()) - UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); -} - -} // namespace net diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h deleted file mode 100644 index 29a6d67..0000000 --- a/net/base/host_resolver_impl.h +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2012 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 - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "base/time.h" -#include "net/base/capturing_net_log.h" -#include "net/base/host_cache.h" -#include "net/base/host_resolver.h" -#include "net/base/host_resolver_proc.h" -#include "net/base/net_export.h" -#include "net/base/network_change_notifier.h" -#include "net/base/prioritized_dispatcher.h" - -namespace net { - -class BoundNetLog; -class DnsClient; -class NetLog; - -// For each hostname that is requested, HostResolver creates a -// HostResolverImpl::Job. When this job gets dispatched it creates a ProcTask -// which runs the given HostResolverProc on a WorkerPool thread. If requests for -// that same host are made during the job's lifetime, 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, fam1) (for host2, fam2) (for hostx, famx) -// / | | / | | / | | -// Request ... Request Request ... Request Request ... Request -// (port1) (port2) (port3) (port4) (port5) (portX) -// -// When a HostResolverImpl::Job finishes, 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! -// -// The HostResolverImpl enforces limits on the maximum number of concurrent -// threads using PrioritizedDispatcher::Limits. -// -// Jobs are ordered in the queue based on their priority and order of arrival. -class NET_EXPORT HostResolverImpl - : public HostResolver, - NON_EXPORTED_BASE(public base::NonThreadSafe), - public NetworkChangeNotifier::IPAddressObserver, - public NetworkChangeNotifier::DNSObserver { - public: - // Parameters for ProcTask which resolves hostnames using HostResolveProc. - // - // |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). - // - // For each attempt, we could start another attempt if host is not resolved - // within |unresponsive_delay| time. We keep attempting to resolve the host - // for |max_retry_attempts|. For every retry attempt, we grow the - // |unresponsive_delay| by the |retry_factor| amount (that is retry interval - // is multiplied by the retry factor each time). Once we have retried - // |max_retry_attempts|, we give up on additional attempts. - // - struct NET_EXPORT_PRIVATE ProcTaskParams { - // Sets up defaults. - ProcTaskParams(HostResolverProc* resolver_proc, size_t max_retry_attempts); - - ~ProcTaskParams(); - - // 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 resolver_proc; - - // Maximum number retry attempts to resolve the hostname. - // Pass HostResolver::kDefaultRetryAttempts to choose a default value. - size_t max_retry_attempts; - - // This is the limit after which we make another attempt to resolve the host - // if the worker thread has not responded yet. - base::TimeDelta unresponsive_delay; - - // Factor to grow |unresponsive_delay| when we re-re-try. - uint32 retry_factor; - }; - - // Creates a HostResolver that first uses the local cache |cache|, and then - // falls back to |proc_params.resolver_proc|. - // - // If |cache| is NULL, then no caching is used. Otherwise we take - // ownership of the |cache| pointer, and will free it during destruction. - // - // |job_limits| specifies the maximum number of jobs that the resolver will - // run at once. This upper-bounds the total number of outstanding - // DNS transactions (not counting retransmissions and retries). - // - // |net_log| must remain valid for the life of the HostResolverImpl. - HostResolverImpl(scoped_ptr cache, - const PrioritizedDispatcher::Limits& job_limits, - const ProcTaskParams& proc_params, - NetLog* net_log); - - // 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(); - - // Configures maximum number of Jobs in the queue. Exposed for testing. - // Only allowed when the queue is empty. - void SetMaxQueuedJobs(size_t value); - - // Set the DnsClient to be used for resolution. In case of failure, the - // HostResolverProc from ProcTaskParams will be queried. If the DnsClient is - // not pre-configured with a valid DnsConfig, a new config is fetched from - // NetworkChangeNotifier. - void SetDnsClient(scoped_ptr dns_client); - - // HostResolver methods: - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& source_net_log) OVERRIDE; - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& source_net_log) OVERRIDE; - virtual void CancelRequest(RequestHandle req) OVERRIDE; - virtual void SetDefaultAddressFamily(AddressFamily address_family) OVERRIDE; - virtual AddressFamily GetDefaultAddressFamily() const OVERRIDE; - virtual void ProbeIPv6Support() OVERRIDE; - virtual void SetDnsClientEnabled(bool enabled) OVERRIDE; - virtual HostCache* GetHostCache() OVERRIDE; - virtual base::Value* GetDnsConfigAsValue() const OVERRIDE; - - private: - friend class HostResolverImplTest; - class Job; - class ProcTask; - class IPv6ProbeJob; - class LoopbackProbeJob; - class DnsTask; - class Request; - typedef HostCache::Key Key; - typedef std::map JobMap; - typedef ScopedVector RequestsList; - - // Helper used by |Resolve()| and |ResolveFromCache()|. Performs IP - // literal, cache and HOSTS lookup (if enabled), returns OK if successful, - // ERR_NAME_NOT_RESOLVED if either hostname is invalid or IP literal is - // incompatible, ERR_DNS_CACHE_MISS if entry was not found in cache and HOSTS. - int ResolveHelper(const Key& key, - const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& request_net_log); - - // Tries to resolve |key| as an IP, returns true and sets |net_error| if - // succeeds, returns false otherwise. - bool ResolveAsIP(const Key& key, - const RequestInfo& info, - int* net_error, - AddressList* addresses); - - // If |key| is not found in cache returns false, otherwise returns - // true, sets |net_error| to the cached error code and fills |addresses| - // if it is a positive entry. - bool ServeFromCache(const Key& key, - const RequestInfo& info, - int* net_error, - AddressList* addresses); - - // If we have a DnsClient with a valid DnsConfig, and |key| is found in the - // HOSTS file, returns true and fills |addresses|. Otherwise returns false. - bool ServeFromHosts(const Key& key, - const RequestInfo& info, - AddressList* addresses); - - // Callback from IPv6 probe activity. - void IPv6ProbeSetDefaultAddressFamily(AddressFamily address_family); - - // Callback from HaveOnlyLoopbackAddresses probe. - void SetHaveOnlyLoopbackAddresses(bool result); - - // Returns the (hostname, address_family) key to use for |info|, choosing an - // "effective" address family by inheriting the resolver's default address - // family when the request leaves it unspecified. - Key GetEffectiveKeyForRequest(const RequestInfo& info) const; - - // Records the result in cache if cache is present. - void CacheResult(const Key& key, - const HostCache::Entry& entry, - base::TimeDelta ttl); - - // Removes |job| from |jobs_|, only if it exists. - void RemoveJob(Job* job); - - // Aborts all in progress jobs with ERR_NETWORK_CHANGED and notifies their - // requests. Might start new jobs. - void AbortAllInProgressJobs(); - - // Attempts to serve each Job in |jobs_| from the HOSTS file if we have - // a DnsClient with a valid DnsConfig. - void TryServingAllJobsFromHosts(); - - // NetworkChangeNotifier::IPAddressObserver: - virtual void OnIPAddressChanged() OVERRIDE; - - // NetworkChangeNotifier::DNSObserver: - virtual void OnDNSChanged() OVERRIDE; - - // True if have a DnsClient with a valid DnsConfig. - bool HaveDnsConfig() const; - - // Called when a host name is successfully resolved and DnsTask was run on it - // and resulted in |net_error|. - void OnDnsTaskResolve(int net_error); - - // Allows the tests to catch slots leaking out of the dispatcher. - size_t num_running_jobs_for_tests() const { - return dispatcher_.num_running_jobs(); - } - - // Cache of host resolution results. - scoped_ptr cache_; - - // Map from HostCache::Key to a Job. - JobMap jobs_; - - // Starts Jobs according to their priority and the configured limits. - PrioritizedDispatcher dispatcher_; - - // Limit on the maximum number of jobs queued in |dispatcher_|. - size_t max_queued_jobs_; - - // Parameters for ProcTask. - ProcTaskParams proc_params_; - - NetLog* net_log_; - - // Address family to use when the request doesn't specify one. - AddressFamily default_address_family_; - - base::WeakPtrFactory weak_ptr_factory_; - - base::WeakPtrFactory probe_weak_ptr_factory_; - - // If present, used by DnsTask and ServeFromHosts to resolve requests. - scoped_ptr dns_client_; - - // True if received valid config from |dns_config_service_|. Temporary, used - // to measure performance of DnsConfigService: http://crbug.com/125599 - bool received_dns_config_; - - // Number of consecutive failures of DnsTask, counted when fallback succeeds. - unsigned num_dns_failures_; - - // Indicate if probing is done after each network change event to set address - // family. When false, explicit setting of address family is used and results - // of the IPv6 probe job are ignored. - bool ipv6_probe_monitoring_; - - // True iff ProcTask has successfully resolved a hostname known to have IPv6 - // addresses using ADDRESS_FAMILY_UNSPECIFIED. Reset on IP address change. - bool resolved_known_ipv6_hostname_; - - // Any resolver flags that should be added to a request by default. - HostResolverFlags additional_resolver_flags_; - - DISALLOW_COPY_AND_ASSIGN(HostResolverImpl); -}; - -} // namespace net - -#endif // NET_BASE_HOST_RESOLVER_IMPL_H_ diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc deleted file mode 100644 index d0c8fcb..0000000 --- a/net/base/host_resolver_impl_unittest.cc +++ /dev/null @@ -1,1481 +0,0 @@ -// Copyright (c) 2012 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" - -#include -#include - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_vector.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "base/stringprintf.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "base/test/test_timeouts.h" -#include "base/time.h" -#include "net/base/address_list.h" -#include "net/base/host_cache.h" -#include "net/base/mock_host_resolver.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/dns/dns_client.h" -#include "net/dns/dns_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -const size_t kMaxJobs = 10u; -const size_t kMaxRetryAttempts = 4u; - -PrioritizedDispatcher::Limits DefaultLimits() { - PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, kMaxJobs); - return limits; -} - -HostResolverImpl::ProcTaskParams DefaultParams( - HostResolverProc* resolver_proc) { - return HostResolverImpl::ProcTaskParams(resolver_proc, kMaxRetryAttempts); -} - -// A HostResolverProc that pushes each host mapped into a list and allows -// waiting for a specific number of requests. Unlike RuleBasedHostResolverProc -// it never calls SystemHostResolverProc. By default resolves all hostnames to -// "127.0.0.1". After AddRule(), it resolves only names explicitly specified. -class MockHostResolverProc : public HostResolverProc { - public: - struct ResolveKey { - ResolveKey(const std::string& hostname, AddressFamily address_family) - : hostname(hostname), address_family(address_family) {} - bool operator<(const ResolveKey& other) const { - return address_family < other.address_family || - (address_family == other.address_family && hostname < other.hostname); - } - std::string hostname; - AddressFamily address_family; - }; - - typedef std::vector CaptureList; - - MockHostResolverProc() - : HostResolverProc(NULL), - num_requests_waiting_(0), - num_slots_available_(0), - requests_waiting_(&lock_), - slots_available_(&lock_) { - } - - // Waits until |count| calls to |Resolve| are blocked. Returns false when - // timed out. - bool WaitFor(unsigned count) { - base::AutoLock lock(lock_); - base::Time start_time = base::Time::Now(); - while (num_requests_waiting_ < count) { - requests_waiting_.TimedWait(TestTimeouts::action_timeout()); - if (base::Time::Now() > start_time + TestTimeouts::action_timeout()) - return false; - } - return true; - } - - // Signals |count| waiting calls to |Resolve|. First come first served. - void SignalMultiple(unsigned count) { - base::AutoLock lock(lock_); - num_slots_available_ += count; - slots_available_.Broadcast(); - } - - // Signals all waiting calls to |Resolve|. Beware of races. - void SignalAll() { - base::AutoLock lock(lock_); - num_slots_available_ = num_requests_waiting_; - slots_available_.Broadcast(); - } - - void AddRule(const std::string& hostname, AddressFamily family, - const AddressList& result) { - base::AutoLock lock(lock_); - rules_[ResolveKey(hostname, family)] = result; - } - - void AddRule(const std::string& hostname, AddressFamily family, - const std::string& ip_list) { - AddressList result; - int rv = ParseAddressList(ip_list, "", &result); - DCHECK_EQ(OK, rv); - AddRule(hostname, family, result); - } - - void AddRuleForAllFamilies(const std::string& hostname, - const std::string& ip_list) { - AddressList result; - int rv = ParseAddressList(ip_list, "", &result); - DCHECK_EQ(OK, rv); - AddRule(hostname, ADDRESS_FAMILY_UNSPECIFIED, result); - AddRule(hostname, ADDRESS_FAMILY_IPV4, result); - AddRule(hostname, ADDRESS_FAMILY_IPV6, result); - } - - virtual int Resolve(const std::string& hostname, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) OVERRIDE { - base::AutoLock lock(lock_); - capture_list_.push_back(ResolveKey(hostname, address_family)); - ++num_requests_waiting_; - requests_waiting_.Broadcast(); - while (!num_slots_available_) - slots_available_.Wait(); - DCHECK_GT(num_requests_waiting_, 0u); - --num_slots_available_; - --num_requests_waiting_; - if (rules_.empty()) { - int rv = ParseAddressList("127.0.0.1", "", addrlist); - DCHECK_EQ(OK, rv); - return OK; - } - ResolveKey key(hostname, address_family); - if (rules_.count(key) == 0) - return ERR_NAME_NOT_RESOLVED; - *addrlist = rules_[key]; - return OK; - } - - CaptureList GetCaptureList() const { - CaptureList copy; - { - base::AutoLock lock(lock_); - copy = capture_list_; - } - return copy; - } - - bool HasBlockedRequests() const { - base::AutoLock lock(lock_); - return num_requests_waiting_ > num_slots_available_; - } - - protected: - virtual ~MockHostResolverProc() {} - - private: - mutable base::Lock lock_; - std::map rules_; - CaptureList capture_list_; - unsigned num_requests_waiting_; - unsigned num_slots_available_; - base::ConditionVariable requests_waiting_; - base::ConditionVariable slots_available_; - - DISALLOW_COPY_AND_ASSIGN(MockHostResolverProc); -}; - -// A wrapper for requests to a HostResolver. -class Request { - public: - // Base class of handlers to be executed on completion of requests. - struct Handler { - virtual ~Handler() {} - virtual void Handle(Request* request) = 0; - }; - - Request(const HostResolver::RequestInfo& info, - size_t index, - HostResolver* resolver, - Handler* handler) - : info_(info), - index_(index), - resolver_(resolver), - handler_(handler), - quit_on_complete_(false), - result_(ERR_UNEXPECTED), - handle_(NULL) {} - - int Resolve() { - DCHECK(resolver_); - DCHECK(!handle_); - list_ = AddressList(); - result_ = resolver_->Resolve( - info_, &list_, base::Bind(&Request::OnComplete, base::Unretained(this)), - &handle_, BoundNetLog()); - if (!list_.empty()) - EXPECT_EQ(OK, result_); - return result_; - } - - int ResolveFromCache() { - DCHECK(resolver_); - DCHECK(!handle_); - return resolver_->ResolveFromCache(info_, &list_, BoundNetLog()); - } - - void Cancel() { - DCHECK(resolver_); - DCHECK(handle_); - resolver_->CancelRequest(handle_); - handle_ = NULL; - } - - const HostResolver::RequestInfo& info() const { return info_; } - size_t index() const { return index_; } - const AddressList& list() const { return list_; } - int result() const { return result_; } - bool completed() const { return result_ != ERR_IO_PENDING; } - bool pending() const { return handle_ != NULL; } - - bool HasAddress(const std::string& address, int port) const { - IPAddressNumber ip; - bool rv = ParseIPLiteralToNumber(address, &ip); - DCHECK(rv); - return std::find(list_.begin(), - list_.end(), - IPEndPoint(ip, port)) != list_.end(); - } - - // Returns the number of addresses in |list_|. - unsigned NumberOfAddresses() const { - return list_.size(); - } - - bool HasOneAddress(const std::string& address, int port) const { - return HasAddress(address, port) && (NumberOfAddresses() == 1u); - } - - // Returns ERR_UNEXPECTED if timed out. - int WaitForResult() { - if (completed()) - return result_; - base::CancelableClosure closure(MessageLoop::QuitClosure()); - MessageLoop::current()->PostDelayedTask(FROM_HERE, - closure.callback(), - TestTimeouts::action_max_timeout()); - quit_on_complete_ = true; - MessageLoop::current()->Run(); - bool did_quit = !quit_on_complete_; - quit_on_complete_ = false; - closure.Cancel(); - if (did_quit) - return result_; - else - return ERR_UNEXPECTED; - } - - private: - void OnComplete(int rv) { - EXPECT_TRUE(pending()); - EXPECT_EQ(ERR_IO_PENDING, result_); - EXPECT_NE(ERR_IO_PENDING, rv); - result_ = rv; - handle_ = NULL; - if (!list_.empty()) { - EXPECT_EQ(OK, result_); - EXPECT_EQ(info_.port(), list_.front().port()); - } - if (handler_) - handler_->Handle(this); - if (quit_on_complete_) { - MessageLoop::current()->Quit(); - quit_on_complete_ = false; - } - } - - HostResolver::RequestInfo info_; - size_t index_; - HostResolver* resolver_; - Handler* handler_; - bool quit_on_complete_; - - AddressList list_; - int result_; - HostResolver::RequestHandle handle_; - - DISALLOW_COPY_AND_ASSIGN(Request); -}; - -// Using LookupAttemptHostResolverProc simulate very long lookups, and control -// which attempt resolves the host. -class LookupAttemptHostResolverProc : public HostResolverProc { - public: - LookupAttemptHostResolverProc(HostResolverProc* previous, - int attempt_number_to_resolve, - int total_attempts) - : HostResolverProc(previous), - attempt_number_to_resolve_(attempt_number_to_resolve), - current_attempt_number_(0), - total_attempts_(total_attempts), - total_attempts_resolved_(0), - resolved_attempt_number_(0), - all_done_(&lock_) { - } - - // Test harness will wait for all attempts to finish before checking the - // results. - void WaitForAllAttemptsToFinish(const base::TimeDelta& wait_time) { - base::TimeTicks end_time = base::TimeTicks::Now() + wait_time; - { - base::AutoLock auto_lock(lock_); - while (total_attempts_resolved_ != total_attempts_ && - base::TimeTicks::Now() < end_time) { - all_done_.TimedWait(end_time - base::TimeTicks::Now()); - } - } - } - - // All attempts will wait for an attempt to resolve the host. - void WaitForAnAttemptToComplete() { - base::TimeDelta wait_time = base::TimeDelta::FromSeconds(60); - base::TimeTicks end_time = base::TimeTicks::Now() + wait_time; - { - base::AutoLock auto_lock(lock_); - while (resolved_attempt_number_ == 0 && base::TimeTicks::Now() < end_time) - all_done_.TimedWait(end_time - base::TimeTicks::Now()); - } - all_done_.Broadcast(); // Tell all waiting attempts to proceed. - } - - // Returns the number of attempts that have finished the Resolve() method. - int total_attempts_resolved() { return total_attempts_resolved_; } - - // Returns the first attempt that that has resolved the host. - int resolved_attempt_number() { return resolved_attempt_number_; } - - // HostResolverProc methods. - virtual int Resolve(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) OVERRIDE { - bool wait_for_right_attempt_to_complete = true; - { - base::AutoLock auto_lock(lock_); - ++current_attempt_number_; - if (current_attempt_number_ == attempt_number_to_resolve_) { - resolved_attempt_number_ = current_attempt_number_; - wait_for_right_attempt_to_complete = false; - } - } - - if (wait_for_right_attempt_to_complete) - // Wait for the attempt_number_to_resolve_ attempt to resolve. - WaitForAnAttemptToComplete(); - - int result = ResolveUsingPrevious(host, address_family, host_resolver_flags, - addrlist, os_error); - - { - base::AutoLock auto_lock(lock_); - ++total_attempts_resolved_; - } - - all_done_.Broadcast(); // Tell all attempts to proceed. - - // Since any negative number is considered a network error, with -1 having - // special meaning (ERR_IO_PENDING). We could return the attempt that has - // resolved the host as a negative number. For example, if attempt number 3 - // resolves the host, then this method returns -4. - if (result == OK) - return -1 - resolved_attempt_number_; - else - return result; - } - - protected: - virtual ~LookupAttemptHostResolverProc() {} - - private: - int attempt_number_to_resolve_; - int current_attempt_number_; // Incremented whenever Resolve is called. - int total_attempts_; - int total_attempts_resolved_; - int resolved_attempt_number_; - - // All attempts wait for right attempt to be resolve. - base::Lock lock_; - base::ConditionVariable all_done_; -}; - -} // namespace - -class HostResolverImplTest : public testing::Test { - public: - static const int kDefaultPort = 80; - - HostResolverImplTest() : proc_(new MockHostResolverProc()) {} - - protected: - // A Request::Handler which is a proxy to the HostResolverImplTest fixture. - struct Handler : public Request::Handler { - virtual ~Handler() {} - - // Proxy functions so that classes derived from Handler can access them. - Request* CreateRequest(const HostResolver::RequestInfo& info) { - return test->CreateRequest(info); - } - Request* CreateRequest(const std::string& hostname, int port) { - return test->CreateRequest(hostname, port); - } - Request* CreateRequest(const std::string& hostname) { - return test->CreateRequest(hostname); - } - ScopedVector& requests() { return test->requests_; } - - void DeleteResolver() { test->resolver_.reset(); } - - HostResolverImplTest* test; - }; - - void CreateResolver() { - resolver_.reset(new HostResolverImpl( - HostCache::CreateDefaultCache(), - DefaultLimits(), - DefaultParams(proc_), - NULL)); - } - - // This HostResolverImpl will only allow 1 outstanding resolve at a time and - // perform no retries. - void CreateSerialResolver() { - HostResolverImpl::ProcTaskParams params = DefaultParams(proc_); - params.max_retry_attempts = 0u; - PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1); - resolver_.reset(new HostResolverImpl( - HostCache::CreateDefaultCache(), - limits, - params, - NULL)); - } - - // The Request will not be made until a call to |Resolve()|, and the Job will - // not start until released by |proc_->SignalXXX|. - Request* CreateRequest(const HostResolver::RequestInfo& info) { - Request* req = new Request(info, requests_.size(), resolver_.get(), - handler_.get()); - requests_.push_back(req); - return req; - } - - Request* CreateRequest(const std::string& hostname, - int port, - RequestPriority priority, - AddressFamily family) { - HostResolver::RequestInfo info(HostPortPair(hostname, port)); - info.set_priority(priority); - info.set_address_family(family); - return CreateRequest(info); - } - - Request* CreateRequest(const std::string& hostname, - int port, - RequestPriority priority) { - return CreateRequest(hostname, port, priority, ADDRESS_FAMILY_UNSPECIFIED); - } - - Request* CreateRequest(const std::string& hostname, int port) { - return CreateRequest(hostname, port, MEDIUM); - } - - Request* CreateRequest(const std::string& hostname) { - return CreateRequest(hostname, kDefaultPort); - } - - virtual void SetUp() OVERRIDE { - CreateResolver(); - } - - virtual void TearDown() OVERRIDE { - if (resolver_.get()) - EXPECT_EQ(0u, resolver_->num_running_jobs_for_tests()); - EXPECT_FALSE(proc_->HasBlockedRequests()); - } - - void set_handler(Handler* handler) { - handler_.reset(handler); - handler_->test = this; - } - - // Friendship is not inherited, so use proxies to access those. - size_t num_running_jobs() const { - DCHECK(resolver_.get()); - return resolver_->num_running_jobs_for_tests(); - } - - scoped_refptr proc_; - scoped_ptr resolver_; - ScopedVector requests_; - - scoped_ptr handler_; -}; - -TEST_F(HostResolverImplTest, AsynchronousLookup) { - proc_->AddRuleForAllFamilies("just.testing", "192.168.1.42"); - proc_->SignalMultiple(1u); - - Request* req = CreateRequest("just.testing", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); - - EXPECT_TRUE(req->HasOneAddress("192.168.1.42", 80)); - - EXPECT_EQ("just.testing", proc_->GetCaptureList()[0].hostname); -} - -TEST_F(HostResolverImplTest, FailedAsynchronousLookup) { - proc_->AddRuleForAllFamilies("", "0.0.0.0"); // Default to failures. - proc_->SignalMultiple(1u); - - Request* req = CreateRequest("just.testing", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->WaitForResult()); - - EXPECT_EQ("just.testing", proc_->GetCaptureList()[0].hostname); - - // Also test that the error is not cached. - EXPECT_EQ(ERR_DNS_CACHE_MISS, req->ResolveFromCache()); -} - -TEST_F(HostResolverImplTest, AbortedAsynchronousLookup) { - Request* req0 = CreateRequest("just.testing", 80); - EXPECT_EQ(ERR_IO_PENDING, req0->Resolve()); - - EXPECT_TRUE(proc_->WaitFor(1u)); - - // Resolver is destroyed while job is running on WorkerPool. - resolver_.reset(); - - proc_->SignalAll(); - - // To ensure there was no spurious callback, complete with a new resolver. - CreateResolver(); - Request* req1 = CreateRequest("just.testing", 80); - EXPECT_EQ(ERR_IO_PENDING, req1->Resolve()); - - proc_->SignalMultiple(2u); - - EXPECT_EQ(OK, req1->WaitForResult()); - - // This request was canceled. - EXPECT_FALSE(req0->completed()); -} - -TEST_F(HostResolverImplTest, NumericIPv4Address) { - // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. - Request* req = CreateRequest("127.1.2.3", 5555); - EXPECT_EQ(OK, req->Resolve()); - - EXPECT_TRUE(req->HasOneAddress("127.1.2.3", 5555)); -} - -TEST_F(HostResolverImplTest, NumericIPv6Address) { - // Resolve a plain IPv6 address. Don't worry about [brackets], because - // the caller should have removed them. - Request* req = CreateRequest("2001:db8::1", 5555); - EXPECT_EQ(OK, req->Resolve()); - - EXPECT_TRUE(req->HasOneAddress("2001:db8::1", 5555)); -} - -TEST_F(HostResolverImplTest, EmptyHost) { - Request* req = CreateRequest("", 5555); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->Resolve()); -} - -TEST_F(HostResolverImplTest, LongHost) { - Request* req = CreateRequest(std::string(4097, 'a'), 5555); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->Resolve()); -} - -TEST_F(HostResolverImplTest, DeDupeRequests) { - // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is - // blocked, these should all pile up until we signal it. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 81)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 82)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); - - proc_->SignalMultiple(2u); // One for "a", one for "b". - - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - } -} - -TEST_F(HostResolverImplTest, CancelMultipleRequests) { - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 81)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 82)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); - - // Cancel everything except request for ("a", 82). - requests_[0]->Cancel(); - requests_[1]->Cancel(); - requests_[2]->Cancel(); - requests_[4]->Cancel(); - - proc_->SignalMultiple(2u); // One for "a", one for "b". - - EXPECT_EQ(OK, requests_[3]->WaitForResult()); -} - -TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) { - // Fill up the dispatcher and queue. - for (unsigned i = 0; i < kMaxJobs + 1; ++i) { - std::string hostname = "a_"; - hostname[1] = 'a' + i; - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 81)->Resolve()); - } - - EXPECT_TRUE(proc_->WaitFor(kMaxJobs)); - - // Cancel all but last two. - for (unsigned i = 0; i < requests_.size() - 2; ++i) { - requests_[i]->Cancel(); - } - - EXPECT_TRUE(proc_->WaitFor(kMaxJobs + 1)); - - proc_->SignalAll(); - - size_t num_requests = requests_.size(); - EXPECT_EQ(OK, requests_[num_requests - 1]->WaitForResult()); - EXPECT_EQ(OK, requests_[num_requests - 2]->result()); -} - -TEST_F(HostResolverImplTest, CancelWithinCallback) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - // Port 80 is the first request that the callback will be invoked for. - // While we are executing within that callback, cancel the other requests - // in the job and start another request. - if (req->index() == 0) { - // Once "a:80" completes, it will cancel "a:81" and "a:82". - requests()[1]->Cancel(); - requests()[2]->Cancel(); - } - } - }; - set_handler(new MyHandler()); - - for (size_t i = 0; i < 4; ++i) { - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; - } - - proc_->SignalMultiple(2u); // One for "a". One for "finalrequest". - - EXPECT_EQ(OK, requests_[0]->WaitForResult()); - - Request* final_request = CreateRequest("finalrequest", 70); - EXPECT_EQ(ERR_IO_PENDING, final_request->Resolve()); - EXPECT_EQ(OK, final_request->WaitForResult()); - EXPECT_TRUE(requests_[3]->completed()); -} - -TEST_F(HostResolverImplTest, DeleteWithinCallback) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - EXPECT_EQ("a", req->info().hostname()); - EXPECT_EQ(80, req->info().port()); - - DeleteResolver(); - - // Quit after returning from OnCompleted (to give it a chance at - // incorrectly running the cancelled tasks). - MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); - } - }; - set_handler(new MyHandler()); - - for (size_t i = 0; i < 4; ++i) { - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; - } - - proc_->SignalMultiple(1u); // One for "a". - - // |MyHandler| will send quit message once all the requests have finished. - MessageLoop::current()->Run(); -} - -TEST_F(HostResolverImplTest, DeleteWithinAbortedCallback) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - EXPECT_EQ("a", req->info().hostname()); - EXPECT_EQ(80, req->info().port()); - - DeleteResolver(); - - // Quit after returning from OnCompleted (to give it a chance at - // incorrectly running the cancelled tasks). - MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); - } - }; - set_handler(new MyHandler()); - - // This test assumes that the Jobs will be Aborted in order ["a", "b"] - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); - // HostResolverImpl will be deleted before later Requests can complete. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 81)->Resolve()); - // Job for 'b' will be aborted before it can complete. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 82)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); - - EXPECT_TRUE(proc_->WaitFor(1u)); - - // Triggering an IP address change. - NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - - // |MyHandler| will send quit message once all the requests have finished. - MessageLoop::current()->Run(); - - EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->result()); - EXPECT_EQ(ERR_IO_PENDING, requests_[1]->result()); - EXPECT_EQ(ERR_IO_PENDING, requests_[2]->result()); - EXPECT_EQ(ERR_IO_PENDING, requests_[3]->result()); - // Clean up. - proc_->SignalMultiple(requests_.size()); -} - -TEST_F(HostResolverImplTest, StartWithinCallback) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - if (req->index() == 0) { - // On completing the first request, start another request for "a". - // Since caching is disabled, this will result in another async request. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 70)->Resolve()); - } - } - }; - set_handler(new MyHandler()); - - // Turn off caching for this host resolver. - resolver_.reset(new HostResolverImpl( - scoped_ptr(), - DefaultLimits(), - DefaultParams(proc_), - NULL)); - - for (size_t i = 0; i < 4; ++i) { - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; - } - - proc_->SignalMultiple(2u); // One for "a". One for the second "a". - - EXPECT_EQ(OK, requests_[0]->WaitForResult()); - ASSERT_EQ(5u, requests_.size()); - EXPECT_EQ(OK, requests_.back()->WaitForResult()); - - EXPECT_EQ(2u, proc_->GetCaptureList().size()); -} - -TEST_F(HostResolverImplTest, BypassCache) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - if (req->index() == 0) { - // On completing the first request, start another request for "a". - // Since caching is enabled, this should complete synchronously. - std::string hostname = req->info().hostname(); - EXPECT_EQ(OK, CreateRequest(hostname, 70)->Resolve()); - EXPECT_EQ(OK, CreateRequest(hostname, 75)->ResolveFromCache()); - - // Ok good. Now make sure that if we ask to bypass the cache, it can no - // longer service the request synchronously. - HostResolver::RequestInfo info(HostPortPair(hostname, 71)); - info.set_allow_cached_response(false); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(info)->Resolve()); - } else if (71 == req->info().port()) { - // Test is done. - MessageLoop::current()->Quit(); - } else { - FAIL() << "Unexpected request"; - } - } - }; - set_handler(new MyHandler()); - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); - proc_->SignalMultiple(3u); // Only need two, but be generous. - - // |verifier| will send quit message once all the requests have finished. - MessageLoop::current()->Run(); - EXPECT_EQ(2u, proc_->GetCaptureList().size()); -} - -// Test that IP address changes flush the cache. -TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) { - proc_->SignalMultiple(2u); // One before the flush, one after. - - Request* req = CreateRequest("host1", 70); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); - - req = CreateRequest("host1", 75); - EXPECT_EQ(OK, req->Resolve()); // Should complete synchronously. - - // Flush cache by triggering an IP address change. - NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - MessageLoop::current()->RunUntilIdle(); // Notification happens async. - - // Resolve "host1" again -- this time it won't be served from cache, so it - // will complete asynchronously. - req = CreateRequest("host1", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); -} - -// Test that IP address changes send ERR_NETWORK_CHANGED to pending requests. -TEST_F(HostResolverImplTest, AbortOnIPAddressChanged) { - Request* req = CreateRequest("host1", 70); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - - EXPECT_TRUE(proc_->WaitFor(1u)); - // Triggering an IP address change. - NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - MessageLoop::current()->RunUntilIdle(); // Notification happens async. - proc_->SignalAll(); - - EXPECT_EQ(ERR_NETWORK_CHANGED, req->WaitForResult()); - EXPECT_EQ(0u, resolver_->GetHostCache()->size()); -} - -// Obey pool constraints after IP address has changed. -TEST_F(HostResolverImplTest, ObeyPoolConstraintsAfterIPAddressChange) { - // Runs at most one job at a time. - CreateSerialResolver(); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a")->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b")->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("c")->Resolve()); - - EXPECT_TRUE(proc_->WaitFor(1u)); - // Triggering an IP address change. - NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - MessageLoop::current()->RunUntilIdle(); // Notification happens async. - proc_->SignalMultiple(3u); // Let the false-start go so that we can catch it. - - EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->WaitForResult()); - - EXPECT_EQ(1u, num_running_jobs()); - - EXPECT_FALSE(requests_[1]->completed()); - EXPECT_FALSE(requests_[2]->completed()); - - EXPECT_EQ(OK, requests_[2]->WaitForResult()); - EXPECT_EQ(OK, requests_[1]->result()); -} - -// Tests that a new Request made from the callback of a previously aborted one -// will not be aborted. -TEST_F(HostResolverImplTest, AbortOnlyExistingRequestsOnIPAddressChange) { - struct MyHandler : public Handler { - virtual void Handle(Request* req) OVERRIDE { - // Start new request for a different hostname to ensure that the order - // of jobs in HostResolverImpl is not stable. - std::string hostname; - if (req->index() == 0) - hostname = "zzz"; - else if (req->index() == 1) - hostname = "aaa"; - else if (req->index() == 2) - hostname = "eee"; - else - return; // A request started from within MyHandler. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname)->Resolve()) << hostname; - } - }; - set_handler(new MyHandler()); - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("bbb")->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("eee")->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ccc")->Resolve()); - - // Wait until all are blocked; - EXPECT_TRUE(proc_->WaitFor(3u)); - // Trigger an IP address change. - NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); - // This should abort all running jobs. - MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->result()); - EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[1]->result()); - EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[2]->result()); - ASSERT_EQ(6u, requests_.size()); - // Unblock all calls to proc. - proc_->SignalMultiple(requests_.size()); - // Run until the re-started requests finish. - EXPECT_EQ(OK, requests_[3]->WaitForResult()); - EXPECT_EQ(OK, requests_[4]->WaitForResult()); - EXPECT_EQ(OK, requests_[5]->WaitForResult()); - // Verify that results of aborted Jobs were not cached. - EXPECT_EQ(6u, proc_->GetCaptureList().size()); - EXPECT_EQ(3u, resolver_->GetHostCache()->size()); -} - -// Tests that when the maximum threads is set to 1, requests are dequeued -// in order of priority. -TEST_F(HostResolverImplTest, HigherPriorityRequestsStartedFirst) { - CreateSerialResolver(); - - // Note that at this point the MockHostResolverProc is blocked, so any - // requests we make will not complete. - CreateRequest("req0", 80, LOW); - CreateRequest("req1", 80, MEDIUM); - CreateRequest("req2", 80, MEDIUM); - CreateRequest("req3", 80, LOW); - CreateRequest("req4", 80, HIGHEST); - CreateRequest("req5", 80, LOW); - CreateRequest("req6", 80, LOW); - CreateRequest("req5", 80, HIGHEST); - - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; - } - - // Unblock the resolver thread so the requests can run. - proc_->SignalMultiple(requests_.size()); // More than needed. - - // Wait for all the requests to complete succesfully. - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - } - - // Since we have restricted to a single concurrent thread in the jobpool, - // the requests should complete in order of priority (with the exception - // of the first request, which gets started right away, since there is - // nothing outstanding). - MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); - ASSERT_EQ(7u, capture_list.size()); - - EXPECT_EQ("req0", capture_list[0].hostname); - EXPECT_EQ("req4", capture_list[1].hostname); - EXPECT_EQ("req5", capture_list[2].hostname); - EXPECT_EQ("req1", capture_list[3].hostname); - EXPECT_EQ("req2", capture_list[4].hostname); - EXPECT_EQ("req3", capture_list[5].hostname); - EXPECT_EQ("req6", capture_list[6].hostname); -} - -// Try cancelling a job which has not started yet. -TEST_F(HostResolverImplTest, CancelPendingRequest) { - CreateSerialResolver(); - - CreateRequest("req0", 80, LOWEST); - CreateRequest("req1", 80, HIGHEST); // Will cancel. - CreateRequest("req2", 80, MEDIUM); - CreateRequest("req3", 80, LOW); - CreateRequest("req4", 80, HIGHEST); // Will cancel. - CreateRequest("req5", 80, LOWEST); // Will cancel. - CreateRequest("req6", 80, MEDIUM); - - // Start all of the requests. - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; - } - - // Cancel some requests - requests_[1]->Cancel(); - requests_[4]->Cancel(); - requests_[5]->Cancel(); - - // Unblock the resolver thread so the requests can run. - proc_->SignalMultiple(requests_.size()); // More than needed. - - // Wait for all the requests to complete succesfully. - for (size_t i = 0; i < requests_.size(); ++i) { - if (!requests_[i]->pending()) - continue; // Don't wait for the requests we cancelled. - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - } - - // Verify that they called out the the resolver proc (which runs on the - // resolver thread) in the expected order. - MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); - ASSERT_EQ(4u, capture_list.size()); - - EXPECT_EQ("req0", capture_list[0].hostname); - EXPECT_EQ("req2", capture_list[1].hostname); - EXPECT_EQ("req6", capture_list[2].hostname); - EXPECT_EQ("req3", capture_list[3].hostname); -} - -// Test that when too many requests are enqueued, old ones start to be aborted. -TEST_F(HostResolverImplTest, QueueOverflow) { - CreateSerialResolver(); - - // Allow only 3 queued jobs. - const size_t kMaxPendingJobs = 3u; - resolver_->SetMaxQueuedJobs(kMaxPendingJobs); - - // Note that at this point the MockHostResolverProc is blocked, so any - // requests we make will not complete. - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req0", 80, LOWEST)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req1", 80, HIGHEST)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req2", 80, MEDIUM)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req3", 80, MEDIUM)->Resolve()); - - // At this point, there are 3 enqueued jobs. - // Insertion of subsequent requests will cause evictions - // based on priority. - - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, - CreateRequest("req4", 80, LOW)->Resolve()); // Evicts itself! - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req5", 80, MEDIUM)->Resolve()); - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[2]->result()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req6", 80, HIGHEST)->Resolve()); - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[3]->result()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req7", 80, MEDIUM)->Resolve()); - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[5]->result()); - - // Unblock the resolver thread so the requests can run. - proc_->SignalMultiple(4u); - - // The rest should succeed. - EXPECT_EQ(OK, requests_[7]->WaitForResult()); - EXPECT_EQ(OK, requests_[0]->result()); - EXPECT_EQ(OK, requests_[1]->result()); - EXPECT_EQ(OK, requests_[6]->result()); - - // Verify that they called out the the resolver proc (which runs on the - // resolver thread) in the expected order. - MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); - ASSERT_EQ(4u, capture_list.size()); - - EXPECT_EQ("req0", capture_list[0].hostname); - EXPECT_EQ("req1", capture_list[1].hostname); - EXPECT_EQ("req6", capture_list[2].hostname); - EXPECT_EQ("req7", capture_list[3].hostname); - - // Verify that the evicted (incomplete) requests were not cached. - EXPECT_EQ(4u, resolver_->GetHostCache()->size()); - - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_TRUE(requests_[i]->completed()) << i; - } -} - -// Tests that after changing the default AddressFamily to IPV4, requests -// with UNSPECIFIED address family map to IPV4. -TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv4) { - CreateSerialResolver(); // To guarantee order of resolutions. - - proc_->AddRule("h1", ADDRESS_FAMILY_IPV4, "1.0.0.1"); - proc_->AddRule("h1", ADDRESS_FAMILY_IPV6, "::2"); - - resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); - - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_UNSPECIFIED); - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV4); - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV6); - - // Start all of the requests. - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; - } - - proc_->SignalMultiple(requests_.size()); - - // Wait for all the requests to complete. - for (size_t i = 0u; i < requests_.size(); ++i) { - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - } - - // Since the requests all had the same priority and we limited the thread - // count to 1, they should have completed in the same order as they were - // requested. Moreover, request0 and request1 will have been serviced by - // the same job. - - MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); - ASSERT_EQ(2u, capture_list.size()); - - EXPECT_EQ("h1", capture_list[0].hostname); - EXPECT_EQ(ADDRESS_FAMILY_IPV4, capture_list[0].address_family); - - EXPECT_EQ("h1", capture_list[1].hostname); - EXPECT_EQ(ADDRESS_FAMILY_IPV6, capture_list[1].address_family); - - // Now check that the correct resolved IP addresses were returned. - EXPECT_TRUE(requests_[0]->HasOneAddress("1.0.0.1", 80)); - EXPECT_TRUE(requests_[1]->HasOneAddress("1.0.0.1", 80)); - EXPECT_TRUE(requests_[2]->HasOneAddress("::2", 80)); -} - -// This is the exact same test as SetDefaultAddressFamily_IPv4, except the -// default family is set to IPv6 and the family of requests is flipped where -// specified. -TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv6) { - CreateSerialResolver(); // To guarantee order of resolutions. - - // Don't use IPv6 replacements here since some systems don't support it. - proc_->AddRule("h1", ADDRESS_FAMILY_IPV4, "1.0.0.1"); - proc_->AddRule("h1", ADDRESS_FAMILY_IPV6, "::2"); - - resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV6); - - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_UNSPECIFIED); - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV6); - CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV4); - - // Start all of the requests. - for (size_t i = 0; i < requests_.size(); ++i) { - EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; - } - - proc_->SignalMultiple(requests_.size()); - - // Wait for all the requests to complete. - for (size_t i = 0u; i < requests_.size(); ++i) { - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - } - - // Since the requests all had the same priority and we limited the thread - // count to 1, they should have completed in the same order as they were - // requested. Moreover, request0 and request1 will have been serviced by - // the same job. - - MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); - ASSERT_EQ(2u, capture_list.size()); - - EXPECT_EQ("h1", capture_list[0].hostname); - EXPECT_EQ(ADDRESS_FAMILY_IPV6, capture_list[0].address_family); - - EXPECT_EQ("h1", capture_list[1].hostname); - EXPECT_EQ(ADDRESS_FAMILY_IPV4, capture_list[1].address_family); - - // Now check that the correct resolved IP addresses were returned. - EXPECT_TRUE(requests_[0]->HasOneAddress("::2", 80)); - EXPECT_TRUE(requests_[1]->HasOneAddress("::2", 80)); - EXPECT_TRUE(requests_[2]->HasOneAddress("1.0.0.1", 80)); -} - -TEST_F(HostResolverImplTest, ResolveFromCache) { - proc_->AddRuleForAllFamilies("just.testing", "192.168.1.42"); - proc_->SignalMultiple(1u); // Need only one. - - HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); - - // First hit will miss the cache. - EXPECT_EQ(ERR_DNS_CACHE_MISS, CreateRequest(info)->ResolveFromCache()); - - // This time, we fetch normally. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(info)->Resolve()); - EXPECT_EQ(OK, requests_[1]->WaitForResult()); - - // Now we should be able to fetch from the cache. - EXPECT_EQ(OK, CreateRequest(info)->ResolveFromCache()); - EXPECT_TRUE(requests_[2]->HasOneAddress("192.168.1.42", 80)); -} - -// Test the retry attempts simulating host resolver proc that takes too long. -TEST_F(HostResolverImplTest, MultipleAttempts) { - // Total number of attempts would be 3 and we want the 3rd attempt to resolve - // the host. First and second attempt will be forced to sleep until they get - // word that a resolution has completed. The 3rd resolution attempt will try - // to get done ASAP, and won't sleep.. - int kAttemptNumberToResolve = 3; - int kTotalAttempts = 3; - - scoped_refptr resolver_proc( - new LookupAttemptHostResolverProc( - NULL, kAttemptNumberToResolve, kTotalAttempts)); - - HostResolverImpl::ProcTaskParams params = DefaultParams(resolver_proc.get()); - - // Specify smaller interval for unresponsive_delay_ for HostResolverImpl so - // that unit test runs faster. For example, this test finishes in 1.5 secs - // (500ms * 3). - params.unresponsive_delay = base::TimeDelta::FromMilliseconds(500); - - resolver_.reset( - new HostResolverImpl(HostCache::CreateDefaultCache(), - DefaultLimits(), - params, - NULL)); - - // Resolve "host1". - HostResolver::RequestInfo info(HostPortPair("host1", 70)); - Request* req = CreateRequest(info); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - - // Resolve returns -4 to indicate that 3rd attempt has resolved the host. - EXPECT_EQ(-4, req->WaitForResult()); - - resolver_proc->WaitForAllAttemptsToFinish( - base::TimeDelta::FromMilliseconds(60000)); - MessageLoop::current()->RunUntilIdle(); - - EXPECT_EQ(resolver_proc->total_attempts_resolved(), kTotalAttempts); - EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); -} - -DnsConfig CreateValidDnsConfig() { - IPAddressNumber dns_ip; - bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); - EXPECT_TRUE(rv); - - DnsConfig config; - config.nameservers.push_back(IPEndPoint(dns_ip, dns_protocol::kDefaultPort)); - EXPECT_TRUE(config.IsValid()); - return config; -} - -// Specialized fixture for tests of DnsTask. -class HostResolverImplDnsTest : public HostResolverImplTest { - protected: - virtual void SetUp() OVERRIDE { - AddDnsRule("er", dns_protocol::kTypeA, MockDnsClientRule::FAIL_SYNC); - AddDnsRule("er", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_SYNC); - AddDnsRule("nx", dns_protocol::kTypeA, MockDnsClientRule::FAIL_ASYNC); - AddDnsRule("nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_ASYNC); - AddDnsRule("ok", dns_protocol::kTypeA, MockDnsClientRule::OK); - AddDnsRule("ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); - AddDnsRule("4ok", dns_protocol::kTypeA, MockDnsClientRule::OK); - AddDnsRule("4ok", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY); - AddDnsRule("6ok", dns_protocol::kTypeA, MockDnsClientRule::EMPTY); - AddDnsRule("6ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); - AddDnsRule("4nx", dns_protocol::kTypeA, MockDnsClientRule::OK); - AddDnsRule("4nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_ASYNC); - CreateResolver(); - } - - void CreateResolver() { - resolver_.reset(new HostResolverImpl( - HostCache::CreateDefaultCache(), - DefaultLimits(), - DefaultParams(proc_), - NULL)); - resolver_->SetDnsClient(CreateMockDnsClient(DnsConfig(), dns_rules_)); - } - - // Adds a rule to |dns_rules_|. Must be followed by |CreateResolver| to apply. - void AddDnsRule(const std::string& prefix, - uint16 qtype, - MockDnsClientRule::Result result) { - dns_rules_.push_back(MockDnsClientRule(prefix, qtype, result)); - } - - void ChangeDnsConfig(const DnsConfig& config) { - NetworkChangeNotifier::SetDnsConfig(config); - // Notification is delivered asynchronously. - MessageLoop::current()->RunUntilIdle(); - } - - MockDnsClientRuleList dns_rules_; -}; - -// TODO(szym): Test AbortAllInProgressJobs due to DnsConfig change. - -// TODO(cbentzel): Test a mix of requests with different HostResolverFlags. - -// Test successful and fallback resolutions in HostResolverImpl::DnsTask. -TEST_F(HostResolverImplDnsTest, DnsTask) { - resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); - - proc_->AddRuleForAllFamilies("er_succeed", "192.168.1.101"); - proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.102"); - // All other hostnames will fail in proc_. - - // Initially there is no config, so client should not be invoked. - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok_fail", 80)->Resolve()); - proc_->SignalMultiple(requests_.size()); - - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[0]->WaitForResult()); - - ChangeDnsConfig(CreateValidDnsConfig()); - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok_fail", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("er_fail", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("nx_fail", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("er_succeed", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("nx_succeed", 80)->Resolve()); - - proc_->SignalMultiple(requests_.size()); - - for (size_t i = 1; i < requests_.size(); ++i) - EXPECT_NE(ERR_UNEXPECTED, requests_[i]->WaitForResult()) << i; - - EXPECT_EQ(OK, requests_[1]->result()); - // Resolved by MockDnsClient. - EXPECT_TRUE(requests_[1]->HasOneAddress("127.0.0.1", 80)); - // Fallback to ProcTask. - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[2]->result()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[3]->result()); - EXPECT_EQ(OK, requests_[4]->result()); - EXPECT_TRUE(requests_[4]->HasOneAddress("192.168.1.101", 80)); - EXPECT_EQ(OK, requests_[5]->result()); - EXPECT_TRUE(requests_[5]->HasOneAddress("192.168.1.102", 80)); -} - -TEST_F(HostResolverImplDnsTest, DnsTaskUnspec) { - ChangeDnsConfig(CreateValidDnsConfig()); - - proc_->AddRuleForAllFamilies("4nx", "192.168.1.101"); - // All other hostnames will fail in proc_. - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4ok", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("6ok", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4nx", 80)->Resolve()); - - proc_->SignalMultiple(requests_.size()); - - for (size_t i = 0; i < requests_.size(); ++i) - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - - EXPECT_EQ(2u, requests_[0]->NumberOfAddresses()); - EXPECT_TRUE(requests_[0]->HasAddress("127.0.0.1", 80)); - EXPECT_TRUE(requests_[0]->HasAddress("::1", 80)); - EXPECT_EQ(1u, requests_[1]->NumberOfAddresses()); - EXPECT_TRUE(requests_[1]->HasAddress("127.0.0.1", 80)); - EXPECT_EQ(1u, requests_[2]->NumberOfAddresses()); - EXPECT_TRUE(requests_[2]->HasAddress("::1", 80)); - EXPECT_EQ(1u, requests_[3]->NumberOfAddresses()); - EXPECT_TRUE(requests_[3]->HasAddress("192.168.1.101", 80)); -} - -TEST_F(HostResolverImplDnsTest, ServeFromHosts) { - // Initially, use empty HOSTS file. - DnsConfig config = CreateValidDnsConfig(); - ChangeDnsConfig(config); - - proc_->AddRuleForAllFamilies("", ""); // Default to failures. - proc_->SignalMultiple(1u); // For the first request which misses. - - Request* req0 = CreateRequest("er_ipv4", 80); - EXPECT_EQ(ERR_IO_PENDING, req0->Resolve()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req0->WaitForResult()); - - IPAddressNumber local_ipv4, local_ipv6; - ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &local_ipv4)); - ASSERT_TRUE(ParseIPLiteralToNumber("::1", &local_ipv6)); - - DnsHosts hosts; - hosts[DnsHostsKey("er_ipv4", ADDRESS_FAMILY_IPV4)] = local_ipv4; - hosts[DnsHostsKey("er_ipv6", ADDRESS_FAMILY_IPV6)] = local_ipv6; - hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV4)] = local_ipv4; - hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV6)] = local_ipv6; - - // Update HOSTS file. - config.hosts = hosts; - ChangeDnsConfig(config); - - Request* req1 = CreateRequest("er_ipv4", 80); - EXPECT_EQ(OK, req1->Resolve()); - EXPECT_TRUE(req1->HasOneAddress("127.0.0.1", 80)); - - Request* req2 = CreateRequest("er_ipv6", 80); - EXPECT_EQ(OK, req2->Resolve()); - EXPECT_TRUE(req2->HasOneAddress("::1", 80)); - - Request* req3 = CreateRequest("er_both", 80); - EXPECT_EQ(OK, req3->Resolve()); - EXPECT_TRUE(req3->HasOneAddress("127.0.0.1", 80) || - req3->HasOneAddress("::1", 80)); - - // Requests with specified AddressFamily. - Request* req4 = CreateRequest("er_ipv4", 80, MEDIUM, ADDRESS_FAMILY_IPV4); - EXPECT_EQ(OK, req4->Resolve()); - EXPECT_TRUE(req4->HasOneAddress("127.0.0.1", 80)); - - Request* req5 = CreateRequest("er_ipv6", 80, MEDIUM, ADDRESS_FAMILY_IPV6); - EXPECT_EQ(OK, req5->Resolve()); - EXPECT_TRUE(req5->HasOneAddress("::1", 80)); - - // Request with upper case. - Request* req6 = CreateRequest("er_IPV4", 80); - EXPECT_EQ(OK, req6->Resolve()); - EXPECT_TRUE(req6->HasOneAddress("127.0.0.1", 80)); -} - -TEST_F(HostResolverImplDnsTest, BypassDnsTask) { - ChangeDnsConfig(CreateValidDnsConfig()); - - proc_->AddRuleForAllFamilies("", ""); // Default to failures. - - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok.local", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok.local.", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("oklocal", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("oklocal.", 80)->Resolve()); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); - - proc_->SignalMultiple(requests_.size()); - - for (size_t i = 0; i < 2; ++i) - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[i]->WaitForResult()) << i; - - for (size_t i = 2; i < requests_.size(); ++i) - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; -} - -TEST_F(HostResolverImplDnsTest, DisableDnsClientOnPersistentFailure) { - ChangeDnsConfig(CreateValidDnsConfig()); - - proc_->AddRuleForAllFamilies("", ""); // Default to failures. - - // Check that DnsTask works. - Request* req = CreateRequest("ok_1", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); - - for (unsigned i = 0; i < 20; ++i) { - // Use custom names to require separate Jobs. - std::string hostname = base::StringPrintf("err_%u", i); - // Ensure fallback to ProcTask succeeds. - proc_->AddRuleForAllFamilies(hostname, "192.168.1.101"); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()) << i; - } - - proc_->SignalMultiple(requests_.size()); - - for (size_t i = 0; i < requests_.size(); ++i) - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - - ASSERT_FALSE(proc_->HasBlockedRequests()); - - // DnsTask should be disabled by now. - req = CreateRequest("ok_2", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - proc_->SignalMultiple(1u); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->WaitForResult()); - - // Check that it is re-enabled after DNS change. - ChangeDnsConfig(CreateValidDnsConfig()); - req = CreateRequest("ok_3", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); -} - -TEST_F(HostResolverImplDnsTest, DontDisableDnsClientOnSporadicFailure) { - ChangeDnsConfig(CreateValidDnsConfig()); - - // |proc_| defaults to successes. - - // 20 failures interleaved with 20 successes. - for (unsigned i = 0; i < 40; ++i) { - // Use custom names to require separate Jobs. - std::string hostname = (i % 2) == 0 ? base::StringPrintf("err_%u", i) - : base::StringPrintf("ok_%u", i); - EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()) << i; - } - - proc_->SignalMultiple(requests_.size()); - - for (size_t i = 0; i < requests_.size(); ++i) - EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; - - // Make |proc_| default to failures. - proc_->AddRuleForAllFamilies("", ""); - - // DnsTask should still be enabled. - Request* req = CreateRequest("ok_last", 80); - EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); - EXPECT_EQ(OK, req->WaitForResult()); -} - -} // namespace net diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc deleted file mode 100644 index 15693fd..0000000 --- a/net/base/host_resolver_proc.cc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2012 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" - -#include "base/logging.h" -#include "base/sys_byteorder.h" -#include "net/base/address_list.h" -#include "net/base/dns_reloader.h" -#include "net/base/net_errors.h" -#include "net/base/sys_addrinfo.h" - -#if defined(OS_OPENBSD) -#define AI_ADDRCONFIG 0 -#endif - -namespace net { - -namespace { - -bool IsAllLocalhostOfOneFamily(const struct addrinfo* ai) { - bool saw_v4_localhost = false; - bool saw_v6_localhost = false; - for (; ai != NULL; ai = ai->ai_next) { - switch (ai->ai_family) { - case AF_INET: { - const struct sockaddr_in* addr_in = - reinterpret_cast(ai->ai_addr); - if ((base::NetToHost32(addr_in->sin_addr.s_addr) & 0xff000000) == - 0x7f000000) - saw_v4_localhost = true; - else - return false; - break; - } - case AF_INET6: { - const struct sockaddr_in6* addr_in6 = - reinterpret_cast(ai->ai_addr); - if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr)) - saw_v6_localhost = true; - else - return false; - break; - } - default: - NOTREACHED(); - return false; - } - } - - return saw_v4_localhost != saw_v6_localhost; -} - -} // namespace - -HostResolverProc* HostResolverProc::default_proc_ = NULL; - -HostResolverProc::HostResolverProc(HostResolverProc* previous) { - SetPreviousProc(previous); - - // Implicitly fall-back to the global default procedure. - if (!previous) - SetPreviousProc(default_proc_); -} - -HostResolverProc::~HostResolverProc() { -} - -int HostResolverProc::ResolveUsingPrevious( - const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) { - if (previous_proc_) { - return previous_proc_->Resolve(host, address_family, host_resolver_flags, - addrlist, os_error); - } - - // Final fallback is the system resolver. - return SystemHostResolverProc(host, address_family, host_resolver_flags, - addrlist, os_error); -} - -void HostResolverProc::SetPreviousProc(HostResolverProc* proc) { - HostResolverProc* current_previous = previous_proc_; - previous_proc_ = NULL; - // Now that we've guaranteed |this| is the last proc in a chain, we can - // detect potential cycles using GetLastProc(). - previous_proc_ = (GetLastProc(proc) == this) ? current_previous : proc; -} - -void HostResolverProc::SetLastProc(HostResolverProc* proc) { - GetLastProc(this)->SetPreviousProc(proc); -} - -// static -HostResolverProc* HostResolverProc::GetLastProc(HostResolverProc* proc) { - if (proc == NULL) - return NULL; - HostResolverProc* last_proc = proc; - while (last_proc->previous_proc_ != NULL) - last_proc = last_proc->previous_proc_; - return last_proc; -} - -// static -HostResolverProc* HostResolverProc::SetDefault(HostResolverProc* proc) { - HostResolverProc* old = default_proc_; - default_proc_ = proc; - return old; -} - -// static -HostResolverProc* HostResolverProc::GetDefault() { - return default_proc_; -} - -int SystemHostResolverProc(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) { - if (os_error) - *os_error = 0; - - struct addrinfo* ai = NULL; - struct addrinfo hints = {0}; - - switch (address_family) { - case ADDRESS_FAMILY_IPV4: - hints.ai_family = AF_INET; - break; - case ADDRESS_FAMILY_IPV6: - hints.ai_family = AF_INET6; - break; - case ADDRESS_FAMILY_UNSPECIFIED: - hints.ai_family = AF_UNSPEC; - break; - default: - NOTREACHED(); - hints.ai_family = AF_UNSPEC; - } - -#if defined(OS_WIN) - // DO NOT USE AI_ADDRCONFIG ON WINDOWS. - // - // The following comment in 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. - // - // OpenBSD does not support it, either. - hints.ai_flags = 0; -#else - hints.ai_flags = AI_ADDRCONFIG; -#endif - - // On Linux AI_ADDRCONFIG doesn't consider loopback addreses, even if only - // loopback addresses are configured. So don't use it when there are only - // loopback addresses. - if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) - hints.ai_flags &= ~AI_ADDRCONFIG; - - if (host_resolver_flags & HOST_RESOLVER_CANONNAME) - hints.ai_flags |= AI_CANONNAME; - - // Restrict result set to only this socket type to avoid duplicates. - hints.ai_socktype = SOCK_STREAM; - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ - !defined(OS_ANDROID) - DnsReloaderMaybeReload(); -#endif - int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); - bool should_retry = false; - // If the lookup was restricted (either by address family, or address - // detection), and the results where all localhost of a single family, - // maybe we should retry. There were several bugs related to these - // issues, for example http://crbug.com/42058 and http://crbug.com/49024 - if ((hints.ai_family != AF_UNSPEC || hints.ai_flags & AI_ADDRCONFIG) && - err == 0 && IsAllLocalhostOfOneFamily(ai)) { - if (host_resolver_flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) { - hints.ai_family = AF_UNSPEC; - should_retry = true; - } - if (hints.ai_flags & AI_ADDRCONFIG) { - hints.ai_flags &= ~AI_ADDRCONFIG; - should_retry = true; - } - } - if (should_retry) { - if (ai != NULL) { - freeaddrinfo(ai); - ai = NULL; - } - err = getaddrinfo(host.c_str(), NULL, &hints, &ai); - } - - if (err) { -#if defined(OS_WIN) - err = WSAGetLastError(); -#endif - - // Return the OS error to the caller. - if (os_error) - *os_error = err; - - // If the call to getaddrinfo() failed because of a system error, report - // it separately from ERR_NAME_NOT_RESOLVED. -#if defined(OS_WIN) - if (err != WSAHOST_NOT_FOUND && err != WSANO_DATA) - return ERR_NAME_RESOLUTION_FAILED; -#elif defined(OS_POSIX) && !defined(OS_FREEBSD) - if (err != EAI_NONAME && err != EAI_NODATA) - return ERR_NAME_RESOLUTION_FAILED; -#endif - - return ERR_NAME_NOT_RESOLVED; - } - -#if defined(OS_ANDROID) - // Workaround for Android's getaddrinfo leaving ai==NULL without an error. - // http://crbug.com/134142 - if (ai == NULL) - return ERR_NAME_NOT_RESOLVED; -#endif - - *addrlist = AddressList::CreateFromAddrinfo(ai); - freeaddrinfo(ai); - return OK; -} - -} // namespace net diff --git a/net/base/host_resolver_proc.h b/net/base/host_resolver_proc.h deleted file mode 100644 index 6131db4f..0000000 --- a/net/base/host_resolver_proc.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2012 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 - -#include "base/memory/ref_counted.h" -#include "net/base/address_family.h" -#include "net/base/net_export.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 NET_EXPORT HostResolverProc - : public base::RefCountedThreadSafe { - public: - explicit HostResolverProc(HostResolverProc* previous); - - // Resolves |host| to an address list, restricting the results to addresses - // in |address_family|. If successful returns OK and fills |addrlist| with - // a list of socket addresses. Otherwise returns a network error code, and - // fills |os_error| with a more specific error if it was non-NULL. - virtual int Resolve(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) = 0; - - protected: - friend class base::RefCountedThreadSafe; - - virtual ~HostResolverProc(); - - // Asks the fallback procedure (if set) to do the resolve. - int ResolveUsingPrevious(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error); - - private: - friend class HostResolverImpl; - friend class MockHostResolverBase; - friend class ScopedDefaultHostResolverProc; - - // Sets the previous procedure in the chain. Aborts if this would result in a - // cycle. - void SetPreviousProc(HostResolverProc* proc); - - // Sets the last procedure in the chain, i.e. appends |proc| to the end of the - // current chain. Aborts if this would result in a cycle. - void SetLastProc(HostResolverProc* proc); - - // Returns the last procedure in the chain starting at |proc|. Will return - // NULL iff |proc| is NULL. - static HostResolverProc* GetLastProc(HostResolverProc* 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(); - - scoped_refptr 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, and fills |os_error| with a more specific error if it -// was non-NULL. -NET_EXPORT_PRIVATE int SystemHostResolverProc( - const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error); - -} // namespace net - -#endif // NET_BASE_HOST_RESOLVER_PROC_H_ diff --git a/net/base/mapped_host_resolver.cc b/net/base/mapped_host_resolver.cc deleted file mode 100644 index a8bd020..0000000 --- a/net/base/mapped_host_resolver.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2012 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/mapped_host_resolver.h" - -#include "base/string_util.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" - -namespace net { - -MappedHostResolver::MappedHostResolver(scoped_ptr impl) - : impl_(impl.Pass()) { -} - -MappedHostResolver::~MappedHostResolver() { -} - -int MappedHostResolver::Resolve(const RequestInfo& original_info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) { - RequestInfo info = original_info; - int rv = ApplyRules(&info); - if (rv != OK) - return rv; - - return impl_->Resolve(info, addresses, callback, out_req, net_log); -} - -int MappedHostResolver::ResolveFromCache(const RequestInfo& original_info, - AddressList* addresses, - const BoundNetLog& net_log) { - RequestInfo info = original_info; - int rv = ApplyRules(&info); - if (rv != OK) - return rv; - - return impl_->ResolveFromCache(info, addresses, net_log); -} - -void MappedHostResolver::CancelRequest(RequestHandle req) { - impl_->CancelRequest(req); -} - -void MappedHostResolver::ProbeIPv6Support() { - impl_->ProbeIPv6Support(); -} - -HostCache* MappedHostResolver::GetHostCache() { - return impl_->GetHostCache(); -} - -int MappedHostResolver::ApplyRules(RequestInfo* info) const { - HostPortPair host_port(info->host_port_pair()); - if (rules_.RewriteHost(&host_port)) { - if (host_port.host() == "~NOTFOUND") - return ERR_NAME_NOT_RESOLVED; - info->set_host_port_pair(host_port); - } - return OK; -} - -} // namespace net diff --git a/net/base/mapped_host_resolver.h b/net/base/mapped_host_resolver.h deleted file mode 100644 index 114e621..0000000 --- a/net/base/mapped_host_resolver.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2012 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_MAPPED_HOST_RESOLVER_H_ -#define NET_BASE_MAPPED_HOST_RESOLVER_H_ - -#include - -#include "base/memory/scoped_ptr.h" -#include "net/base/host_mapping_rules.h" -#include "net/base/host_resolver.h" -#include "net/base/net_export.h" - -namespace net { - -// This class wraps an existing HostResolver instance, but modifies the -// request before passing it off to |impl|. This is different from -// MockHostResolver which does the remapping at the HostResolverProc -// layer, so it is able to preserve the effectiveness of the cache. -class NET_EXPORT MappedHostResolver : public HostResolver { - public: - // Creates a MappedHostResolver that forwards all of its requests through - // |impl|. - explicit MappedHostResolver(scoped_ptr impl); - virtual ~MappedHostResolver(); - - // Adds a rule to this mapper. The format of the rule can be one of: - // - // "MAP" [":" ] - // "EXCLUDE" - // - // The can be either a hostname, or an IP address literal, - // or "~NOTFOUND". If it is "~NOTFOUND" then all matched hostnames will fail - // to be resolved with ERR_NAME_NOT_RESOLVED. - // - // Returns true if the rule was successfully parsed and added. - bool AddRuleFromString(const std::string& rule_string) { - return rules_.AddRuleFromString(rule_string); - } - - // Takes a comma separated list of rules, and assigns them to this resolver. - void SetRulesFromString(const std::string& rules_string) { - rules_.SetRulesFromString(rules_string); - } - - // HostResolver methods: - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) OVERRIDE; - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) OVERRIDE; - virtual void CancelRequest(RequestHandle req) OVERRIDE; - virtual void ProbeIPv6Support() OVERRIDE; - virtual HostCache* GetHostCache() OVERRIDE; - - private: - // Modify the request |info| according to |rules_|. Returns either OK or - // the network error code that the hostname's resolution mapped to. - int ApplyRules(RequestInfo* info) const; - - scoped_ptr impl_; - - HostMappingRules rules_; -}; - -} // namespace net - -#endif // NET_BASE_MAPPED_HOST_RESOLVER_H_ diff --git a/net/base/mapped_host_resolver_unittest.cc b/net/base/mapped_host_resolver_unittest.cc deleted file mode 100644 index 35fe011..0000000 --- a/net/base/mapped_host_resolver_unittest.cc +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2012 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/mapped_host_resolver.h" - -#include "net/base/address_list.h" -#include "net/base/mock_host_resolver.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" -#include "net/base/net_util.h" -#include "net/base/test_completion_callback.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -std::string FirstAddress(const AddressList& address_list) { - if (address_list.empty()) - return ""; - return address_list.front().ToString(); -} - -TEST(MappedHostResolverTest, Inclusion) { - // Create a mock host resolver, with specific hostname to IP mappings. - scoped_ptr resolver_impl(new MockHostResolver()); - resolver_impl->rules()->AddSimulatedFailure("*google.com"); - resolver_impl->rules()->AddRule("baz.com", "192.168.1.5"); - resolver_impl->rules()->AddRule("foo.com", "192.168.1.8"); - resolver_impl->rules()->AddRule("proxy", "192.168.1.11"); - - // Create a remapped resolver that uses |resolver_impl|. - scoped_ptr resolver( - new MappedHostResolver(resolver_impl.PassAs())); - - int rv; - AddressList address_list; - - // Try resolving "www.google.com:80". There are no mappings yet, so this - // hits |resolver_impl| and fails. - TestCompletionCallback callback; - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.google.com", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); - - // Remap *.google.com to baz.com. - EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com")); - - // Try resolving "www.google.com:80". Should be remapped to "baz.com:80". - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.google.com", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); - - // Try resolving "foo.com:77". This will NOT be remapped, so result - // is "foo.com:77". - rv = resolver->Resolve(HostResolver::RequestInfo(HostPortPair("foo.com", 77)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.8:77", FirstAddress(address_list)); - - // Remap "*.org" to "proxy:99". - EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99")); - - // Try resolving "chromium.org:61". Should be remapped to "proxy:99". - rv = resolver->Resolve(HostResolver::RequestInfo - (HostPortPair("chromium.org", 61)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.11:99", FirstAddress(address_list)); -} - -// Tests that exclusions are respected. -TEST(MappedHostResolverTest, Exclusion) { - // Create a mock host resolver, with specific hostname to IP mappings. - scoped_ptr resolver_impl(new MockHostResolver()); - resolver_impl->rules()->AddRule("baz", "192.168.1.5"); - resolver_impl->rules()->AddRule("www.google.com", "192.168.1.3"); - - // Create a remapped resolver that uses |resolver_impl|. - scoped_ptr resolver( - new MappedHostResolver(resolver_impl.PassAs())); - - int rv; - AddressList address_list; - TestCompletionCallback callback; - - // Remap "*.com" to "baz". - EXPECT_TRUE(resolver->AddRuleFromString("map *.com baz")); - - // Add an exclusion for "*.google.com". - EXPECT_TRUE(resolver->AddRuleFromString("EXCLUDE *.google.com")); - - // Try resolving "www.google.com". Should not be remapped due to exclusion). - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.google.com", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.3:80", FirstAddress(address_list)); - - // Try resolving "chrome.com:80". Should be remapped to "baz:80". - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("chrome.com", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); -} - -TEST(MappedHostResolverTest, SetRulesFromString) { - // Create a mock host resolver, with specific hostname to IP mappings. - scoped_ptr resolver_impl(new MockHostResolver()); - resolver_impl->rules()->AddRule("baz", "192.168.1.7"); - resolver_impl->rules()->AddRule("bar", "192.168.1.9"); - - // Create a remapped resolver that uses |resolver_impl|. - scoped_ptr resolver( - new MappedHostResolver(resolver_impl.PassAs())); - - int rv; - AddressList address_list; - TestCompletionCallback callback; - - // Remap "*.com" to "baz", and *.net to "bar:60". - resolver->SetRulesFromString("map *.com baz , map *.net bar:60"); - - // Try resolving "www.google.com". Should be remapped to "baz". - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.google.com", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.7:80", FirstAddress(address_list)); - - // Try resolving "chrome.net:80". Should be remapped to "bar:60". - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("chrome.net", 80)), - &address_list, callback.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.9:60", FirstAddress(address_list)); -} - -// Parsing bad rules should silently discard the rule (and never crash). -TEST(MappedHostResolverTest, ParseInvalidRules) { - scoped_ptr resolver( - new MappedHostResolver(scoped_ptr())); - - EXPECT_FALSE(resolver->AddRuleFromString("xyz")); - EXPECT_FALSE(resolver->AddRuleFromString("")); - EXPECT_FALSE(resolver->AddRuleFromString(" ")); - EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE")); - EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE foo bar")); - EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE")); - EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x")); - EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x :10")); -} - -// Test mapping hostnames to resolving failures. -TEST(MappedHostResolverTest, MapToError) { - scoped_ptr resolver_impl(new MockHostResolver()); - resolver_impl->rules()->AddRule("*", "192.168.1.5"); - - scoped_ptr resolver( - new MappedHostResolver(resolver_impl.PassAs())); - - int rv; - AddressList address_list; - - // Remap *.google.com to resolving failures. - EXPECT_TRUE(resolver->AddRuleFromString("MAP *.google.com ~NOTFOUND")); - - // Try resolving www.google.com --> Should give an error. - TestCompletionCallback callback1; - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.google.com", 80)), - &address_list, callback1.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); - - // Try resolving www.foo.com --> Should succeed. - TestCompletionCallback callback2; - rv = resolver->Resolve(HostResolver::RequestInfo( - HostPortPair("www.foo.com", 80)), - &address_list, callback2.callback(), NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback2.WaitForResult(); - EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); -} - -} // namespace - -} // namespace net diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc deleted file mode 100644 index 47554fe..0000000 --- a/net/base/mock_host_resolver.cc +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2012 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 -#include - -#include "base/bind.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop.h" -#include "base/stl_util.h" -#include "base/string_util.h" -#include "base/strings/string_split.h" -#include "base/threading/platform_thread.h" -#include "net/base/host_cache.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/base/test_completion_callback.h" -#if defined(OS_WIN) -#include "net/base/winsock_init.h" -#endif - -namespace net { - -namespace { - -// Cache size for the MockCachingHostResolver. -const unsigned kMaxCacheEntries = 100; -// TTL for the successful resolutions. Failures are not cached. -const unsigned kCacheEntryTTLSeconds = 60; - -} // namespace - -int ParseAddressList(const std::string& host_list, - const std::string& canonical_name, - AddressList* addrlist) { - *addrlist = AddressList(); - std::vector addresses; - base::SplitString(host_list, ',', &addresses); - addrlist->set_canonical_name(canonical_name); - for (size_t index = 0; index < addresses.size(); ++index) { - IPAddressNumber ip_number; - if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) { - LOG(WARNING) << "Not a supported IP literal: " << addresses[index]; - return ERR_UNEXPECTED; - } - addrlist->push_back(IPEndPoint(ip_number, -1)); - } - return OK; -} - -struct MockHostResolverBase::Request { - Request(const RequestInfo& req_info, - AddressList* addr, - const CompletionCallback& cb) - : info(req_info), addresses(addr), callback(cb) {} - RequestInfo info; - AddressList* addresses; - CompletionCallback callback; -}; - -MockHostResolverBase::~MockHostResolverBase() { - STLDeleteValues(&requests_); -} - -int MockHostResolverBase::Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* handle, - const BoundNetLog& net_log) { - DCHECK(CalledOnValidThread()); - num_resolve_++; - size_t id = next_request_id_++; - int rv = ResolveFromIPLiteralOrCache(info, addresses); - if (rv != ERR_DNS_CACHE_MISS) { - return rv; - } - if (synchronous_mode_) { - return ResolveProc(id, info, addresses); - } - // Store the request for asynchronous resolution - Request* req = new Request(info, addresses, callback); - requests_[id] = req; - if (handle) - *handle = reinterpret_cast(id); - - if (!ondemand_mode_) { - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), id)); - } - - return ERR_IO_PENDING; -} - -int MockHostResolverBase::ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) { - num_resolve_from_cache_++; - DCHECK(CalledOnValidThread()); - next_request_id_++; - int rv = ResolveFromIPLiteralOrCache(info, addresses); - return rv; -} - -void MockHostResolverBase::CancelRequest(RequestHandle handle) { - DCHECK(CalledOnValidThread()); - size_t id = reinterpret_cast(handle); - RequestMap::iterator it = requests_.find(id); - if (it != requests_.end()) { - scoped_ptr req(it->second); - requests_.erase(it); - } else { - NOTREACHED() << "CancelRequest must NOT be called after request is " - "complete or canceled."; - } -} - -HostCache* MockHostResolverBase::GetHostCache() { - return cache_.get(); -} - -void MockHostResolverBase::ResolveAllPending() { - DCHECK(CalledOnValidThread()); - DCHECK(ondemand_mode_); - for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) { - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), i->first)); - } -} - -// start id from 1 to distinguish from NULL RequestHandle -MockHostResolverBase::MockHostResolverBase(bool use_caching) - : synchronous_mode_(false), - ondemand_mode_(false), - next_request_id_(1), - num_resolve_(0), - num_resolve_from_cache_(0) { - rules_ = CreateCatchAllHostResolverProc(); - - if (use_caching) { - cache_.reset(new HostCache(kMaxCacheEntries)); - } -} - -int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info, - AddressList* addresses) { - IPAddressNumber ip; - if (ParseIPLiteralToNumber(info.hostname(), &ip)) { - *addresses = AddressList::CreateFromIPAddress(ip, info.port()); - if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME) - addresses->SetDefaultCanonicalName(); - return OK; - } - int rv = ERR_DNS_CACHE_MISS; - if (cache_.get() && info.allow_cached_response()) { - HostCache::Key key(info.hostname(), - info.address_family(), - info.host_resolver_flags()); - const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now()); - if (entry) { - rv = entry->error; - if (rv == OK) - *addresses = AddressList::CopyWithPort(entry->addrlist, info.port()); - } - } - return rv; -} - -int MockHostResolverBase::ResolveProc(size_t id, - const RequestInfo& info, - AddressList* addresses) { - AddressList addr; - int rv = rules_->Resolve(info.hostname(), - info.address_family(), - info.host_resolver_flags(), - &addr, - NULL); - if (cache_.get()) { - HostCache::Key key(info.hostname(), - info.address_family(), - info.host_resolver_flags()); - // Storing a failure with TTL 0 so that it overwrites previous value. - base::TimeDelta ttl; - if (rv == OK) - ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); - cache_->Set(key, HostCache::Entry(rv, addr), base::TimeTicks::Now(), ttl); - } - if (rv == OK) - *addresses = AddressList::CopyWithPort(addr, info.port()); - return rv; -} - -void MockHostResolverBase::ResolveNow(size_t id) { - RequestMap::iterator it = requests_.find(id); - if (it == requests_.end()) - return; // was canceled - - scoped_ptr req(it->second); - requests_.erase(it); - int rv = ResolveProc(id, req->info, req->addresses); - if (!req->callback.is_null()) - req->callback.Run(rv); -} - -//----------------------------------------------------------------------------- - -struct RuleBasedHostResolverProc::Rule { - enum ResolverType { - kResolverTypeFail, - kResolverTypeSystem, - kResolverTypeIPLiteral, - }; - - ResolverType resolver_type; - std::string host_pattern; - AddressFamily address_family; - HostResolverFlags host_resolver_flags; - std::string replacement; - std::string canonical_name; - int latency_ms; // In milliseconds. - - Rule(ResolverType resolver_type, - const std::string& host_pattern, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - const std::string& replacement, - const std::string& canonical_name, - int latency_ms) - : resolver_type(resolver_type), - host_pattern(host_pattern), - address_family(address_family), - host_resolver_flags(host_resolver_flags), - replacement(replacement), - canonical_name(canonical_name), - latency_ms(latency_ms) {} -}; - -RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous) - : HostResolverProc(previous) { -} - -void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern, - const std::string& replacement) { - AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED, - replacement); -} - -void RuleBasedHostResolverProc::AddRuleForAddressFamily( - const std::string& host_pattern, - AddressFamily address_family, - const std::string& replacement) { - DCHECK(!replacement.empty()); - HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags, - replacement, "", 0); - rules_.push_back(rule); -} - -void RuleBasedHostResolverProc::AddIPLiteralRule( - const std::string& host_pattern, - const std::string& ip_literal, - const std::string& canonical_name) { - // Literals are always resolved to themselves by HostResolverImpl, - // consequently we do not support remapping them. - IPAddressNumber ip_number; - DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number)); - HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - if (!canonical_name.empty()) - flags |= HOST_RESOLVER_CANONNAME; - Rule rule(Rule::kResolverTypeIPLiteral, host_pattern, - ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name, - 0); - rules_.push_back(rule); -} - -void RuleBasedHostResolverProc::AddRuleWithLatency( - const std::string& host_pattern, - const std::string& replacement, - int latency_ms) { - DCHECK(!replacement.empty()); - HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, - flags, replacement, "", latency_ms); - rules_.push_back(rule); -} - -void RuleBasedHostResolverProc::AllowDirectLookup( - const std::string& host_pattern) { - HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, - flags, "", "", 0); - rules_.push_back(rule); -} - -void RuleBasedHostResolverProc::AddSimulatedFailure( - const std::string& host_pattern) { - HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; - Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, - flags, "", "", 0); - rules_.push_back(rule); -} - -void RuleBasedHostResolverProc::ClearRules() { - rules_.clear(); -} - -int RuleBasedHostResolverProc::Resolve(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) { - RuleList::iterator r; - for (r = rules_.begin(); r != rules_.end(); ++r) { - bool matches_address_family = - r->address_family == ADDRESS_FAMILY_UNSPECIFIED || - r->address_family == address_family; - // Flags match if all of the bitflags in host_resolver_flags are enabled - // in the rule's host_resolver_flags. However, the rule may have additional - // flags specified, in which case the flags should still be considered a - // match. - bool matches_flags = (r->host_resolver_flags & host_resolver_flags) == - host_resolver_flags; - if (matches_flags && matches_address_family && - MatchPattern(host, r->host_pattern)) { - if (r->latency_ms != 0) { - base::PlatformThread::Sleep( - base::TimeDelta::FromMilliseconds(r->latency_ms)); - } - - // Remap to a new host. - const std::string& effective_host = - r->replacement.empty() ? host : r->replacement; - - // Apply the resolving function to the remapped hostname. - switch (r->resolver_type) { - case Rule::kResolverTypeFail: - return ERR_NAME_NOT_RESOLVED; - case Rule::kResolverTypeSystem: -#if defined(OS_WIN) - net::EnsureWinsockInit(); -#endif - return SystemHostResolverProc(effective_host, - address_family, - host_resolver_flags, - addrlist, os_error); - case Rule::kResolverTypeIPLiteral: - return ParseAddressList(effective_host, - r->canonical_name, - addrlist); - default: - NOTREACHED(); - return ERR_UNEXPECTED; - } - } - } - return ResolveUsingPrevious(host, address_family, - host_resolver_flags, addrlist, os_error); -} - -RuleBasedHostResolverProc::~RuleBasedHostResolverProc() { -} - -RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() { - RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL); - catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost"); - - // Next add a rules-based layer the use controls. - return new RuleBasedHostResolverProc(catchall); -} - -//----------------------------------------------------------------------------- - -int HangingHostResolver::Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) { - return ERR_IO_PENDING; -} - -int HangingHostResolver::ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) { - return ERR_DNS_CACHE_MISS; -} - -//----------------------------------------------------------------------------- - -ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {} - -ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc( - HostResolverProc* proc) { - Init(proc); -} - -ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() { - HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_); - // The lifetimes of multiple instances must be nested. - CHECK_EQ(old_proc, current_proc_); -} - -void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) { - current_proc_ = proc; - previous_proc_ = HostResolverProc::SetDefault(current_proc_); - current_proc_->SetLastProc(previous_proc_); -} - -} // namespace net diff --git a/net/base/mock_host_resolver.h b/net/base/mock_host_resolver.h deleted file mode 100644 index ee6f1b5..0000000 --- a/net/base/mock_host_resolver.h +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2011 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 -#include - -#include "base/memory/weak_ptr.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/non_thread_safe.h" -#include "net/base/host_resolver.h" -#include "net/base/host_resolver_proc.h" - -namespace net { - -class HostCache; -class RuleBasedHostResolverProc; - -// Fills |*addrlist| with a socket address for |host_list| which should be a -// comma-separated list of IPv4 or IPv6 literal(s) without enclosing brackets. -// If |canonical_name| is non-empty it is used as the DNS canonical name for -// the host. Returns OK on success, ERR_UNEXPECTED otherwise. -int ParseAddressList(const std::string& host_list, - const std::string& canonical_name, - AddressList* addrlist); - -// In most cases, it is important that unit tests avoid relying on 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. -// -// By default, MockHostResolvers include a single rule that maps all hosts to -// 127.0.0.1. - -// Base class shared by MockHostResolver and MockCachingHostResolver. -class MockHostResolverBase : public HostResolver, - public base::SupportsWeakPtr, - public base::NonThreadSafe { - public: - virtual ~MockHostResolverBase(); - - RuleBasedHostResolverProc* rules() { return rules_; } - void set_rules(RuleBasedHostResolverProc* rules) { rules_ = rules; } - - // Controls whether resolutions complete synchronously or asynchronously. - void set_synchronous_mode(bool is_synchronous) { - synchronous_mode_ = is_synchronous; - } - - // Asynchronous requests are automatically resolved by default. - // If set_ondemand_mode() is set then Resolve() returns IO_PENDING and - // ResolveAllPending() must be explicitly invoked to resolve all requests - // that are pending. - void set_ondemand_mode(bool is_ondemand) { - ondemand_mode_ = is_ondemand; - } - - // HostResolver methods: - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) OVERRIDE; - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) OVERRIDE; - virtual void CancelRequest(RequestHandle req) OVERRIDE; - virtual HostCache* GetHostCache() OVERRIDE; - - // Resolves all pending requests. It is only valid to invoke this if - // set_ondemand_mode was set before. The requests are resolved asynchronously, - // after this call returns. - void ResolveAllPending(); - - // Returns true if there are pending requests that can be resolved by invoking - // ResolveAllPending(). - bool has_pending_requests() const { return !requests_.empty(); } - - // The number of times that Resolve() has been called. - size_t num_resolve() const { - return num_resolve_; - } - - // The number of times that ResolveFromCache() has been called. - size_t num_resolve_from_cache() const { - return num_resolve_from_cache_; - } - - protected: - explicit MockHostResolverBase(bool use_caching); - - private: - struct Request; - typedef std::map RequestMap; - - // Resolve as IP or from |cache_| return cached error or - // DNS_CACHE_MISS if failed. - int ResolveFromIPLiteralOrCache(const RequestInfo& info, - AddressList* addresses); - // Resolve via |proc_|. - int ResolveProc(size_t id, const RequestInfo& info, AddressList* addresses); - // Resolve request stored in |requests_|. Pass rv to callback. - void ResolveNow(size_t id); - - bool synchronous_mode_; - bool ondemand_mode_; - scoped_refptr rules_; - scoped_ptr cache_; - RequestMap requests_; - size_t next_request_id_; - - size_t num_resolve_; - size_t num_resolve_from_cache_; - - DISALLOW_COPY_AND_ASSIGN(MockHostResolverBase); -}; - -class MockHostResolver : public MockHostResolverBase { - public: - MockHostResolver() : MockHostResolverBase(false /*use_caching*/) {} - virtual ~MockHostResolver() {} -}; - -// Same as MockHostResolver, except internally it uses a host-cache. -// -// Note that tests are advised to use MockHostResolver instead, since it is -// more predictable. (MockHostResolver also can be put into synchronous -// operation mode in case that is what you needed from the caching version). -class MockCachingHostResolver : public MockHostResolverBase { - public: - MockCachingHostResolver() : MockHostResolverBase(true /*use_caching*/) {} - virtual ~MockCachingHostResolver() {} -}; - -// 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); - - // 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); - - // Same as AddRule(), but further restricts to |address_family|. - void AddRuleForAddressFamily(const std::string& host_pattern, - AddressFamily address_family, - const std::string& replacement); - - // Same as AddRule(), but the replacement is expected to be an IPv4 or IPv6 - // literal. This can be used in place of AddRule() to bypass the system's - // host resolver (the address list will be constructed manually). - // If |canonical_name| is non-empty, it is copied to the resulting AddressList - // but does not impact DNS resolution. - // |ip_literal| can be a single IP address like "192.168.1.1" or a comma - // separated list of IP addresses, like "::1,192:168.1.2". - void AddIPLiteralRule(const std::string& host_pattern, - const std::string& ip_literal, - const std::string& canonical_name); - - 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); - - // Deletes all the rules that have been added. - void ClearRules(); - - // HostResolverProc methods: - virtual int Resolve(const std::string& host, - AddressFamily address_family, - HostResolverFlags host_resolver_flags, - AddressList* addrlist, - int* os_error) OVERRIDE; - - private: - struct Rule; - typedef std::list RuleList; - - virtual ~RuleBasedHostResolverProc(); - - RuleList rules_; -}; - -// Create rules that map all requests to localhost. -RuleBasedHostResolverProc* CreateCatchAllHostResolverProc(); - -// HangingHostResolver never completes its |Resolve| request. -class HangingHostResolver : public HostResolver { - public: - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) OVERRIDE; - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) OVERRIDE; - virtual void CancelRequest(RequestHandle req) OVERRIDE {} -}; - -// This class sets the default HostResolverProc for a particular scope. The -// chain of resolver procs starting at |proc| is placed in front of any existing -// default resolver proc(s). This means that if multiple -// ScopedDefaultHostResolverProcs are declared, then resolving will start with -// the procs given to the last-allocated one, then fall back to the procs given -// to the previously-allocated one, and so forth. -// -// 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 current_proc_; - scoped_refptr previous_proc_; -}; - -} // namespace net - -#endif // NET_BASE_MOCK_HOST_RESOLVER_H_ diff --git a/net/base/single_request_host_resolver.cc b/net/base/single_request_host_resolver.cc deleted file mode 100644 index b975c00..0000000 --- a/net/base/single_request_host_resolver.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 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/single_request_host_resolver.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "net/base/net_errors.h" - -namespace net { - -SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver) - : resolver_(resolver), - cur_request_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(callback_( - base::Bind(&SingleRequestHostResolver::OnResolveCompletion, - base::Unretained(this)))) { - DCHECK(resolver_ != NULL); -} - -SingleRequestHostResolver::~SingleRequestHostResolver() { - Cancel(); -} - -int SingleRequestHostResolver::Resolve( - const HostResolver::RequestInfo& info, AddressList* addresses, - const CompletionCallback& callback, const BoundNetLog& net_log) { - DCHECK(addresses); - DCHECK_EQ(false, callback.is_null()); - DCHECK(cur_request_callback_.is_null()) << "resolver already in use"; - - HostResolver::RequestHandle request = NULL; - - // We need to be notified of completion before |callback| is called, so that - // we can clear out |cur_request_*|. - CompletionCallback transient_callback = - callback.is_null() ? CompletionCallback() : callback_; - - int rv = resolver_->Resolve( - info, addresses, transient_callback, &request, net_log); - - if (rv == ERR_IO_PENDING) { - DCHECK_EQ(false, callback.is_null()); - // Cleared in OnResolveCompletion(). - cur_request_ = request; - cur_request_callback_ = callback; - } - - return rv; -} - -void SingleRequestHostResolver::Cancel() { - if (!cur_request_callback_.is_null()) { - resolver_->CancelRequest(cur_request_); - cur_request_ = NULL; - cur_request_callback_.Reset(); - } -} - -void SingleRequestHostResolver::OnResolveCompletion(int result) { - DCHECK(cur_request_); - DCHECK_EQ(false, cur_request_callback_.is_null()); - - CompletionCallback callback = cur_request_callback_; - - // Clear the outstanding request information. - cur_request_ = NULL; - cur_request_callback_.Reset(); - - // Call the user's original callback. - callback.Run(result); -} - -} // namespace net diff --git a/net/base/single_request_host_resolver.h b/net/base/single_request_host_resolver.h deleted file mode 100644 index 89d249f..0000000 --- a/net/base/single_request_host_resolver.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2011 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_SINGLE_REQUEST_HOST_RESOLVER_H_ -#define NET_BASE_SINGLE_REQUEST_HOST_RESOLVER_H_ - -#include "net/base/host_resolver.h" - -namespace net { - -// This class represents the task of resolving a hostname (or IP address -// literal) to an AddressList object. It wraps HostResolver to resolve only a -// single hostname at a time and cancels this request when going out of scope. -class NET_EXPORT SingleRequestHostResolver { - public: - // |resolver| must remain valid for the lifetime of |this|. - explicit SingleRequestHostResolver(HostResolver* resolver); - - // If a completion callback is pending when the resolver is destroyed, the - // host resolution is cancelled, and the completion callback will not be - // called. - ~SingleRequestHostResolver(); - - // Resolves the given hostname (or IP address literal), filling out the - // |addresses| object upon success. See HostResolver::Resolve() for details. - int Resolve(const HostResolver::RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - const BoundNetLog& net_log); - - // Cancels the in-progress request, if any. This prevents the callback - // from being invoked. Resolve() can be called again after cancelling. - void Cancel(); - - private: - // Callback for when the request to |resolver_| completes, so we dispatch - // to the user's callback. - void OnResolveCompletion(int result); - - // The actual host resolver that will handle the request. - HostResolver* const resolver_; - - // The current request (if any). - HostResolver::RequestHandle cur_request_; - CompletionCallback cur_request_callback_; - - // Completion callback for when request to |resolver_| completes. - CompletionCallback callback_; - - DISALLOW_COPY_AND_ASSIGN(SingleRequestHostResolver); -}; - -} // namespace net - -#endif // NET_BASE_SINGLE_REQUEST_HOST_RESOLVER_H_ diff --git a/net/base/single_request_host_resolver_unittest.cc b/net/base/single_request_host_resolver_unittest.cc deleted file mode 100644 index b23a722..0000000 --- a/net/base/single_request_host_resolver_unittest.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2012 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/single_request_host_resolver.h" - -#include "net/base/address_list.h" -#include "net/base/mock_host_resolver.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" -#include "net/base/test_completion_callback.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -// Helper class used by SingleRequestHostResolverTest.Cancel test. -// It checks that only one request is outstanding at a time, and that -// it is cancelled before the class is destroyed. -class HangingHostResolver : public HostResolver { - public: - HangingHostResolver() : outstanding_request_(NULL) {} - - virtual ~HangingHostResolver() { - EXPECT_TRUE(!has_outstanding_request()); - } - - bool has_outstanding_request() const { - return outstanding_request_ != NULL; - } - - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) OVERRIDE { - EXPECT_FALSE(has_outstanding_request()); - outstanding_request_ = reinterpret_cast(0x1234); - *out_req = outstanding_request_; - - // Never complete this request! Caller is expected to cancel it - // before destroying the resolver. - return ERR_IO_PENDING; - } - - virtual int ResolveFromCache(const RequestInfo& info, - AddressList* addresses, - const BoundNetLog& net_log) OVERRIDE { - NOTIMPLEMENTED(); - return ERR_UNEXPECTED; - } - - virtual void CancelRequest(RequestHandle req) OVERRIDE { - EXPECT_TRUE(has_outstanding_request()); - EXPECT_EQ(req, outstanding_request_); - outstanding_request_ = NULL; - } - - private: - RequestHandle outstanding_request_; - - DISALLOW_COPY_AND_ASSIGN(HangingHostResolver); -}; - -// Test that a regular end-to-end lookup returns the expected result. -TEST(SingleRequestHostResolverTest, NormalResolve) { - // Create a host resolver dependency that returns address "199.188.1.166" - // for resolutions of "watsup". - MockHostResolver resolver; - resolver.rules()->AddIPLiteralRule("watsup", "199.188.1.166", ""); - - SingleRequestHostResolver single_request_resolver(&resolver); - - // Resolve "watsup:90" using our SingleRequestHostResolver. - AddressList addrlist; - TestCompletionCallback callback; - HostResolver::RequestInfo request(HostPortPair("watsup", 90)); - int rv = single_request_resolver.Resolve( - request, &addrlist, callback.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_EQ(OK, callback.WaitForResult()); - - // Verify that the result is what we specified in the MockHostResolver. - ASSERT_FALSE(addrlist.empty()); - EXPECT_EQ("199.188.1.166", addrlist.front().ToStringWithoutPort()); -} - -// Test that the Cancel() method cancels any outstanding request. -TEST(SingleRequestHostResolverTest, Cancel) { - HangingHostResolver resolver; - - { - SingleRequestHostResolver single_request_resolver(&resolver); - - // Resolve "watsup:90" using our SingleRequestHostResolver. - AddressList addrlist; - TestCompletionCallback callback; - HostResolver::RequestInfo request(HostPortPair("watsup", 90)); - int rv = single_request_resolver.Resolve( - request, &addrlist, callback.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_TRUE(resolver.has_outstanding_request()); - } - - // Now that the SingleRequestHostResolver has been destroyed, the - // in-progress request should have been aborted. - EXPECT_FALSE(resolver.has_outstanding_request()); -} - -// Test that the Cancel() method is a no-op when there is no outstanding -// request. -TEST(SingleRequestHostResolverTest, CancelWhileNoPendingRequest) { - HangingHostResolver resolver; - SingleRequestHostResolver single_request_resolver(&resolver); - single_request_resolver.Cancel(); - - // To pass, HangingHostResolver should not have received a cancellation - // request (since there is nothing to cancel). If it does, it will crash. -} - -} // namespace - -} // namespace net diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc new file mode 100644 index 0000000..6350d2e --- /dev/null +++ b/net/dns/host_resolver.cc @@ -0,0 +1,148 @@ +// Copyright (c) 2012 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/dns/host_resolver.h" + +#include "base/logging.h" +#include "base/metrics/field_trial.h" +#include "base/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "net/base/host_cache.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/host_resolver_impl.h" + +namespace net { + +namespace { + +// Maximum of 6 concurrent resolver threads (excluding retries). +// Some routers (or resolvers) appear to start to provide host-not-found if +// too many simultaneous resolutions are pending. This number needs to be +// further optimized, but 8 is what FF currently does. We found some routers +// that limit this to 6, so we're temporarily holding it at that level. +const size_t kDefaultMaxProcTasks = 6u; + +// When configuring from field trial, do not allow +const size_t kSaneMaxProcTasks = 20u; + +PrioritizedDispatcher::Limits GetDispatcherLimits( + const HostResolver::Options& options) { + PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, + options.max_concurrent_resolves); + + // If not using default, do not use the field trial. + if (limits.total_jobs != HostResolver::kDefaultParallelism) + return limits; + + // Default, without trial is no reserved slots. + limits.total_jobs = kDefaultMaxProcTasks; + + // Parallelism is determined by the field trial. + std::string group = base::FieldTrialList::FindFullName( + "HostResolverDispatch"); + + if (group.empty()) + return limits; + + // The format of the group name is a list of non-negative integers separated + // by ':'. Each of the elements in the list corresponds to an element in + // |reserved_slots|, except the last one which is the |total_jobs|. + + std::vector group_parts; + base::SplitString(group, ':', &group_parts); + if (group_parts.size() != NUM_PRIORITIES + 1) { + NOTREACHED(); + return limits; + } + + std::vector parsed(group_parts.size()); + size_t total_reserved_slots = 0; + + for (size_t i = 0; i < group_parts.size(); ++i) { + if (!base::StringToSizeT(group_parts[i], &parsed[i])) { + NOTREACHED(); + return limits; + } + } + + size_t total_jobs = parsed.back(); + parsed.pop_back(); + for (size_t i = 0; i < parsed.size(); ++i) { + total_reserved_slots += parsed[i]; + } + + // There must be some unreserved slots available for the all priorities. + if (total_reserved_slots > total_jobs || + (total_reserved_slots == total_jobs && parsed[MINIMUM_PRIORITY] == 0)) { + NOTREACHED(); + return limits; + } + + limits.total_jobs = total_jobs; + limits.reserved_slots = parsed; + return limits; +} + +} // namespace + +HostResolver::Options::Options() + : max_concurrent_resolves(kDefaultParallelism), + max_retry_attempts(kDefaultRetryAttempts), + enable_caching(true) { +} + +HostResolver::RequestInfo::RequestInfo(const HostPortPair& host_port_pair) + : host_port_pair_(host_port_pair), + address_family_(ADDRESS_FAMILY_UNSPECIFIED), + host_resolver_flags_(0), + allow_cached_response_(true), + is_speculative_(false), + priority_(MEDIUM) { +} + +HostResolver::~HostResolver() { +} + +AddressFamily HostResolver::GetDefaultAddressFamily() const { + return ADDRESS_FAMILY_UNSPECIFIED; +} + +void HostResolver::ProbeIPv6Support() { +} + +void HostResolver::SetDnsClientEnabled(bool enabled) { +} + +HostCache* HostResolver::GetHostCache() { + return NULL; +} + +base::Value* HostResolver::GetDnsConfigAsValue() const { + return NULL; +} + +// static +scoped_ptr +HostResolver::CreateSystemResolver(const Options& options, NetLog* net_log) { + scoped_ptr cache; + if (options.enable_caching) + cache = HostCache::CreateDefaultCache(); + return scoped_ptr(new HostResolverImpl( + cache.Pass(), + GetDispatcherLimits(options), + HostResolverImpl::ProcTaskParams(NULL, options.max_retry_attempts), + net_log)); +} + +// static +scoped_ptr +HostResolver::CreateDefaultResolver(NetLog* net_log) { + return CreateSystemResolver(Options(), net_log); +} + +HostResolver::HostResolver() { +} + +} // namespace net diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h new file mode 100644 index 0000000..1adf8b7 --- /dev/null +++ b/net/dns/host_resolver.h @@ -0,0 +1,208 @@ +// Copyright (c) 2012 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_DNS_HOST_RESOLVER_H_ +#define NET_DNS_HOST_RESOLVER_H_ + +#include + +#include "base/memory/scoped_ptr.h" +#include "net/base/address_family.h" +#include "net/base/completion_callback.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_export.h" +#include "net/base/net_util.h" +#include "net/base/request_priority.h" + +namespace base { +class Value; +} + +namespace net { + +class AddressList; +class BoundNetLog; +class HostCache; +class HostResolverProc; +class NetLog; + +// This class represents the task of resolving hostnames (or IP address +// literal) to an AddressList object. +// +// 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). +class NET_EXPORT HostResolver { + public: + // |max_concurrent_resolves| is how many resolve requests will be allowed to + // run in parallel. Pass HostResolver::kDefaultParallelism to choose a + // default value. + // |max_retry_attempts| is the maximum number of times we will retry for host + // resolution. Pass HostResolver::kDefaultRetryAttempts to choose a default + // value. + // |enable_caching| controls whether a HostCache is used. + struct NET_EXPORT Options { + Options(); + + size_t max_concurrent_resolves; + size_t max_retry_attempts; + bool enable_caching; + }; + + // The parameters for doing a Resolve(). A hostname and port are required, + // the rest are optional (and have reasonable defaults). + class NET_EXPORT RequestInfo { + public: + explicit RequestInfo(const HostPortPair& host_port_pair); + + const HostPortPair& host_port_pair() const { return host_port_pair_; } + void set_host_port_pair(const HostPortPair& host_port_pair) { + host_port_pair_ = host_port_pair; + } + + int port() const { return host_port_pair_.port(); } + const std::string& hostname() const { return host_port_pair_.host(); } + + AddressFamily address_family() const { return address_family_; } + void set_address_family(AddressFamily address_family) { + address_family_ = address_family; + } + + HostResolverFlags host_resolver_flags() const { + return host_resolver_flags_; + } + void set_host_resolver_flags(HostResolverFlags host_resolver_flags) { + host_resolver_flags_ = host_resolver_flags; + } + + bool allow_cached_response() const { return allow_cached_response_; } + void set_allow_cached_response(bool b) { allow_cached_response_ = b; } + + bool is_speculative() const { return is_speculative_; } + void set_is_speculative(bool b) { is_speculative_ = b; } + + RequestPriority priority() const { return priority_; } + void set_priority(RequestPriority priority) { priority_ = priority; } + + private: + // The hostname to resolve, and the port to use in resulting sockaddrs. + HostPortPair host_port_pair_; + + // The address family to restrict results to. + AddressFamily address_family_; + + // Flags to use when resolving this request. + HostResolverFlags host_resolver_flags_; + + // Whether it is ok to return a result from the host cache. + bool allow_cached_response_; + + // Whether this request was started by the DNS prefetcher. + bool is_speculative_; + + // The priority for the request. + RequestPriority priority_; + }; + + // Opaque type used to cancel a request. + typedef void* RequestHandle; + + // This value can be passed into CreateSystemResolver as the + // |max_concurrent_resolves| parameter. It will select a default level of + // concurrency. + static const size_t kDefaultParallelism = 0; + + // This value can be passed into CreateSystemResolver as the + // |max_retry_attempts| parameter. + static const size_t kDefaultRetryAttempts = -1; + + // 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 ~HostResolver(); + + // Resolves the given hostname (or IP address literal), filling out the + // |addresses| object upon success. The |info.port| parameter will be set as + // the sin(6)_port field of the sockaddr_in{6} struct. Returns OK if + // successful or an error code upon failure. Returns + // ERR_NAME_NOT_RESOLVED if hostname is invalid, or if it is an + // incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6 + // literal). + // + // If the operation cannot be completed synchronously, ERR_IO_PENDING will + // be returned and the real result code will be passed to the completion + // callback. Otherwise the result code is returned immediately from this + // call. + // + // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to + // the async request. This handle is not valid after the request has + // completed. + // + // Profiling information for the request is saved to |net_log| if non-NULL. + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) = 0; + + // Resolves the given hostname (or IP address literal) out of cache or HOSTS + // file (if enabled) only. This is guaranteed to complete synchronously. + // This acts like |Resolve()| if the hostname is IP literal, or cached value + // or HOSTS entry exists. Otherwise, ERR_DNS_CACHE_MISS is returned. + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) = 0; + + // Cancels the specified request. |req| is the handle returned by Resolve(). + // After a request is canceled, its completion callback will not be called. + // CancelRequest must NOT be called after the request's completion callback + // has already run or the request was canceled. + virtual void CancelRequest(RequestHandle req) = 0; + + // Sets the default AddressFamily to use when requests have left it + // unspecified. For example, this could be used to restrict resolution + // results to AF_INET by passing in ADDRESS_FAMILY_IPV4, or to + // AF_INET6 by passing in ADDRESS_FAMILY_IPV6. + virtual void SetDefaultAddressFamily(AddressFamily address_family) {} + virtual AddressFamily GetDefaultAddressFamily() const; + + // Continuously observe whether IPv6 is supported, and set the allowable + // address family to IPv4 iff IPv6 is not supported. + virtual void ProbeIPv6Support(); + + // Enable or disable the built-in asynchronous DnsClient. + virtual void SetDnsClientEnabled(bool enabled); + + // Returns the HostResolverCache |this| uses, or NULL if there isn't one. + // Used primarily to clear the cache and for getting debug information. + virtual HostCache* GetHostCache(); + + // Returns the current DNS configuration |this| is using, as a Value, or NULL + // if it's configured to always use the system host resolver. Caller takes + // ownership of the returned Value. + virtual base::Value* GetDnsConfigAsValue() const; + + // 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). + static scoped_ptr CreateSystemResolver( + const Options& options, + NetLog* net_log); + + // As above, but uses default parameters. + static scoped_ptr CreateDefaultResolver(NetLog* net_log); + + protected: + HostResolver(); + + private: + DISALLOW_COPY_AND_ASSIGN(HostResolver); +}; + +} // namespace net + +#endif // NET_DNS_HOST_RESOLVER_H_ diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc new file mode 100644 index 0000000..91475ec --- /dev/null +++ b/net/dns/host_resolver_impl.cc @@ -0,0 +1,2180 @@ +// Copyright (c) 2012 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/dns/host_resolver_impl.h" + +#if defined(OS_WIN) +#include +#elif defined(OS_POSIX) +#include +#endif + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/debug/debugger.h" +#include "base/debug/stack_trace.h" +#include "base/message_loop_proxy.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/histogram.h" +#include "base/stl_util.h" +#include "base/string_util.h" +#include "base/threading/worker_pool.h" +#include "base/time.h" +#include "base/utf_string_conversions.h" +#include "base/values.h" +#include "net/base/address_family.h" +#include "net/base/address_list.h" +#include "net/base/dns_reloader.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/base/net_util.h" +#include "net/dns/address_sorter.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_config_service.h" +#include "net/dns/dns_protocol.h" +#include "net/dns/dns_response.h" +#include "net/dns/dns_transaction.h" +#include "net/dns/host_resolver_proc.h" + +#if defined(OS_WIN) +#include "net/base/winsock_init.h" +#endif + +namespace net { + +namespace { + +// Limit the size of hostnames that will be resolved to combat issues in +// some platform's resolvers. +const size_t kMaxHostLength = 4096; + +// Default TTL for successful resolutions with ProcTask. +const unsigned kCacheEntryTTLSeconds = 60; + +// Default TTL for unsuccessful resolutions with ProcTask. +const unsigned kNegativeCacheEntryTTLSeconds = 0; + +// Minimum TTL for successful resolutions with DnsTask. +const unsigned kMinimumTTLSeconds = kCacheEntryTTLSeconds; + +// Number of consecutive failures of DnsTask (with successful fallback) before +// the DnsClient is disabled until the next DNS change. +const unsigned kMaximumDnsFailures = 16; + +// We use a separate histogram name for each platform to facilitate the +// display of error codes by their symbolic name (since each platform has +// different mappings). +const char kOSErrorsForGetAddrinfoHistogramName[] = +#if defined(OS_WIN) + "Net.OSErrorsForGetAddrinfo_Win"; +#elif defined(OS_MACOSX) + "Net.OSErrorsForGetAddrinfo_Mac"; +#elif defined(OS_LINUX) + "Net.OSErrorsForGetAddrinfo_Linux"; +#else + "Net.OSErrorsForGetAddrinfo"; +#endif + +// Gets a list of the likely error codes that getaddrinfo() can return +// (non-exhaustive). These are the error codes that we will track via +// a histogram. +std::vector GetAllGetAddrinfoOSErrors() { + int os_errors[] = { +#if defined(OS_POSIX) +#if !defined(OS_FREEBSD) +#if !defined(OS_ANDROID) + // EAI_ADDRFAMILY has been declared obsolete in Android's and + // FreeBSD's netdb.h. + EAI_ADDRFAMILY, +#endif + // EAI_NODATA has been declared obsolete in FreeBSD's netdb.h. + EAI_NODATA, +#endif + EAI_AGAIN, + EAI_BADFLAGS, + EAI_FAIL, + EAI_FAMILY, + EAI_MEMORY, + EAI_NONAME, + EAI_SERVICE, + EAI_SOCKTYPE, + EAI_SYSTEM, +#elif defined(OS_WIN) + // See: http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx + WSA_NOT_ENOUGH_MEMORY, + WSAEAFNOSUPPORT, + WSAEINVAL, + WSAESOCKTNOSUPPORT, + WSAHOST_NOT_FOUND, + WSANO_DATA, + WSANO_RECOVERY, + WSANOTINITIALISED, + WSATRY_AGAIN, + WSATYPE_NOT_FOUND, + // The following are not in doc, but might be to appearing in results :-(. + WSA_INVALID_HANDLE, +#endif + }; + + // Ensure all errors are positive, as histogram only tracks positive values. + for (size_t i = 0; i < arraysize(os_errors); ++i) { + os_errors[i] = std::abs(os_errors[i]); + } + + return base::CustomHistogram::ArrayToCustomRanges(os_errors, + arraysize(os_errors)); +} + +enum DnsResolveStatus { + RESOLVE_STATUS_DNS_SUCCESS = 0, + RESOLVE_STATUS_PROC_SUCCESS, + RESOLVE_STATUS_FAIL, + RESOLVE_STATUS_SUSPECT_NETBIOS, + RESOLVE_STATUS_MAX +}; + +void UmaAsyncDnsResolveStatus(DnsResolveStatus result) { + UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ResolveStatus", + result, + RESOLVE_STATUS_MAX); +} + +bool ResemblesNetBIOSName(const std::string& hostname) { + return (hostname.size() < 16) && (hostname.find('.') == std::string::npos); +} + +// True if |hostname| ends with either ".local" or ".local.". +bool ResemblesMulticastDNSName(const std::string& hostname) { + DCHECK(!hostname.empty()); + const char kSuffix[] = ".local."; + const size_t kSuffixLen = sizeof(kSuffix) - 1; + const size_t kSuffixLenTrimmed = kSuffixLen - 1; + if (hostname[hostname.size() - 1] == '.') { + return hostname.size() > kSuffixLen && + !hostname.compare(hostname.size() - kSuffixLen, kSuffixLen, kSuffix); + } + return hostname.size() > kSuffixLenTrimmed && + !hostname.compare(hostname.size() - kSuffixLenTrimmed, kSuffixLenTrimmed, + kSuffix, kSuffixLenTrimmed); +} + +// Provide a common macro to simplify code and readability. We must use a +// macro as the underlying HISTOGRAM macro creates static variables. +#define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100) + +// A macro to simplify code and readability. +#define DNS_HISTOGRAM_BY_PRIORITY(basename, priority, time) \ + do { \ + switch (priority) { \ + case HIGHEST: DNS_HISTOGRAM(basename "_HIGHEST", time); break; \ + case MEDIUM: DNS_HISTOGRAM(basename "_MEDIUM", time); break; \ + case LOW: DNS_HISTOGRAM(basename "_LOW", time); break; \ + case LOWEST: DNS_HISTOGRAM(basename "_LOWEST", time); break; \ + case IDLE: DNS_HISTOGRAM(basename "_IDLE", time); break; \ + default: NOTREACHED(); break; \ + } \ + DNS_HISTOGRAM(basename, time); \ + } while (0) + +// Record time from Request creation until a valid DNS response. +void RecordTotalTime(bool had_dns_config, + bool speculative, + base::TimeDelta duration) { + if (had_dns_config) { + if (speculative) { + DNS_HISTOGRAM("AsyncDNS.TotalTime_speculative", duration); + } else { + DNS_HISTOGRAM("AsyncDNS.TotalTime", duration); + } + } else { + if (speculative) { + DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); + } else { + DNS_HISTOGRAM("DNS.TotalTime", duration); + } + } +} + +void RecordTTL(base::TimeDelta ttl) { + UMA_HISTOGRAM_CUSTOM_TIMES("AsyncDNS.TTL", ttl, + base::TimeDelta::FromSeconds(1), + base::TimeDelta::FromDays(1), 100); +} + +//----------------------------------------------------------------------------- + +// Wraps call to SystemHostResolverProc as an instance of HostResolverProc. +// TODO(szym): This should probably be declared in host_resolver_proc.h. +class CallSystemHostResolverProc : public HostResolverProc { + public: + CallSystemHostResolverProc() : HostResolverProc(NULL) {} + virtual int Resolve(const std::string& hostname, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addr_list, + int* os_error) OVERRIDE { + return SystemHostResolverProc(hostname, + address_family, + host_resolver_flags, + addr_list, + os_error); + } + + protected: + virtual ~CallSystemHostResolverProc() {} +}; + +AddressList EnsurePortOnAddressList(const AddressList& list, uint16 port) { + if (list.empty() || list.front().port() == port) + return list; + return AddressList::CopyWithPort(list, port); +} + +// Creates NetLog parameters when the resolve failed. +base::Value* NetLogProcTaskFailedCallback(uint32 attempt_number, + int net_error, + int os_error, + NetLog::LogLevel /* log_level */) { + DictionaryValue* dict = new DictionaryValue(); + if (attempt_number) + dict->SetInteger("attempt_number", attempt_number); + + dict->SetInteger("net_error", net_error); + + if (os_error) { + dict->SetInteger("os_error", os_error); +#if defined(OS_POSIX) + dict->SetString("os_error_string", gai_strerror(os_error)); +#elif defined(OS_WIN) + // Map the error code to a human-readable string. + LPWSTR error_string = NULL; + int size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + 0, // Use the internal message table. + os_error, + 0, // Use default language. + (LPWSTR)&error_string, + 0, // Buffer size. + 0); // Arguments (unused). + dict->SetString("os_error_string", WideToUTF8(error_string)); + LocalFree(error_string); +#endif + } + + return dict; +} + +// Creates NetLog parameters when the DnsTask failed. +base::Value* NetLogDnsTaskFailedCallback(int net_error, + int dns_error, + NetLog::LogLevel /* log_level */) { + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger("net_error", net_error); + if (dns_error) + dict->SetInteger("dns_error", dns_error); + return dict; +}; + +// Creates NetLog parameters containing the information in a RequestInfo object, +// along with the associated NetLog::Source. +base::Value* NetLogRequestInfoCallback(const NetLog::Source& source, + const HostResolver::RequestInfo* info, + NetLog::LogLevel /* log_level */) { + DictionaryValue* dict = new DictionaryValue(); + source.AddToEventParameters(dict); + + dict->SetString("host", info->host_port_pair().ToString()); + dict->SetInteger("address_family", + static_cast(info->address_family())); + dict->SetBoolean("allow_cached_response", info->allow_cached_response()); + dict->SetBoolean("is_speculative", info->is_speculative()); + dict->SetInteger("priority", info->priority()); + return dict; +} + +// Creates NetLog parameters for the creation of a HostResolverImpl::Job. +base::Value* NetLogJobCreationCallback(const NetLog::Source& source, + const std::string* host, + NetLog::LogLevel /* log_level */) { + DictionaryValue* dict = new DictionaryValue(); + source.AddToEventParameters(dict); + dict->SetString("host", *host); + return dict; +} + +// Creates NetLog parameters for HOST_RESOLVER_IMPL_JOB_ATTACH/DETACH events. +base::Value* NetLogJobAttachCallback(const NetLog::Source& source, + RequestPriority priority, + NetLog::LogLevel /* log_level */) { + DictionaryValue* dict = new DictionaryValue(); + source.AddToEventParameters(dict); + dict->SetInteger("priority", priority); + return dict; +} + +// Creates NetLog parameters for the DNS_CONFIG_CHANGED event. +base::Value* NetLogDnsConfigCallback(const DnsConfig* config, + NetLog::LogLevel /* log_level */) { + return config->ToValue(); +} + +// The logging routines are defined here because some requests are resolved +// without a Request object. + +// Logs when a request has just been started. +void LogStartRequest(const BoundNetLog& source_net_log, + const BoundNetLog& request_net_log, + const HostResolver::RequestInfo& info) { + source_net_log.BeginEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL, + request_net_log.source().ToEventParametersCallback()); + + request_net_log.BeginEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, + base::Bind(&NetLogRequestInfoCallback, source_net_log.source(), &info)); +} + +// Logs when a request has just completed (before its callback is run). +void LogFinishRequest(const BoundNetLog& source_net_log, + const BoundNetLog& request_net_log, + const HostResolver::RequestInfo& info, + int net_error) { + request_net_log.EndEventWithNetErrorCode( + NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST, net_error); + source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); +} + +// Logs when a request has been cancelled. +void LogCancelRequest(const BoundNetLog& source_net_log, + const BoundNetLog& request_net_log, + const HostResolverImpl::RequestInfo& info) { + request_net_log.AddEvent(NetLog::TYPE_CANCELLED); + request_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_REQUEST); + source_net_log.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL); +} + +//----------------------------------------------------------------------------- + +// Keeps track of the highest priority. +class PriorityTracker { + public: + explicit PriorityTracker(RequestPriority initial_priority) + : highest_priority_(initial_priority), total_count_(0) { + memset(counts_, 0, sizeof(counts_)); + } + + RequestPriority highest_priority() const { + return highest_priority_; + } + + size_t total_count() const { + return total_count_; + } + + void Add(RequestPriority req_priority) { + ++total_count_; + ++counts_[req_priority]; + if (highest_priority_ < req_priority) + highest_priority_ = req_priority; + } + + void Remove(RequestPriority req_priority) { + DCHECK_GT(total_count_, 0u); + DCHECK_GT(counts_[req_priority], 0u); + --total_count_; + --counts_[req_priority]; + size_t i; + for (i = highest_priority_; i > MINIMUM_PRIORITY && !counts_[i]; --i); + highest_priority_ = static_cast(i); + + // In absence of requests, default to MINIMUM_PRIORITY. + if (total_count_ == 0) + DCHECK_EQ(MINIMUM_PRIORITY, highest_priority_); + } + + private: + RequestPriority highest_priority_; + size_t total_count_; + size_t counts_[NUM_PRIORITIES]; +}; + +} // namespace + +//----------------------------------------------------------------------------- + +// Holds the data for a request that could not be completed synchronously. +// It is owned by a Job. Canceled Requests are only marked as canceled rather +// than removed from the Job's |requests_| list. +class HostResolverImpl::Request { + public: + Request(const BoundNetLog& source_net_log, + const BoundNetLog& request_net_log, + const RequestInfo& info, + const CompletionCallback& callback, + AddressList* addresses) + : source_net_log_(source_net_log), + request_net_log_(request_net_log), + info_(info), + job_(NULL), + callback_(callback), + addresses_(addresses), + request_time_(base::TimeTicks::Now()) { + } + + // Mark the request as canceled. + void MarkAsCanceled() { + job_ = NULL; + addresses_ = NULL; + callback_.Reset(); + } + + bool was_canceled() const { + return callback_.is_null(); + } + + void set_job(Job* job) { + DCHECK(job); + // Identify which job the request is waiting on. + job_ = job; + } + + // Prepare final AddressList and call completion callback. + void OnComplete(int error, const AddressList& addr_list) { + DCHECK(!was_canceled()); + if (error == OK) + *addresses_ = EnsurePortOnAddressList(addr_list, info_.port()); + CompletionCallback callback = callback_; + MarkAsCanceled(); + callback.Run(error); + } + + Job* job() const { + return job_; + } + + // NetLog for the source, passed in HostResolver::Resolve. + const BoundNetLog& source_net_log() { + return source_net_log_; + } + + // NetLog for this request. + const BoundNetLog& request_net_log() { + return request_net_log_; + } + + const RequestInfo& info() const { + return info_; + } + + base::TimeTicks request_time() const { + return request_time_; + } + + private: + BoundNetLog source_net_log_; + BoundNetLog request_net_log_; + + // The request info that started the request. + RequestInfo info_; + + // The resolve job 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_; + + const base::TimeTicks request_time_; + + DISALLOW_COPY_AND_ASSIGN(Request); +}; + +//------------------------------------------------------------------------------ + +// Calls HostResolverProc on the WorkerPool. Performs retries if necessary. +// +// Whenever we try to resolve the host, we post a delayed task to check if host +// resolution (OnLookupComplete) is completed or not. If the original attempt +// hasn't completed, then we start another attempt for host resolution. We take +// the results from the first attempt that finishes and ignore the results from +// all other attempts. +// +// TODO(szym): Move to separate source file for testing and mocking. +// +class HostResolverImpl::ProcTask + : public base::RefCountedThreadSafe { + public: + typedef base::Callback Callback; + + ProcTask(const Key& key, + const ProcTaskParams& params, + const Callback& callback, + const BoundNetLog& job_net_log) + : key_(key), + params_(params), + callback_(callback), + origin_loop_(base::MessageLoopProxy::current()), + attempt_number_(0), + completed_attempt_number_(0), + completed_attempt_error_(ERR_UNEXPECTED), + had_non_speculative_request_(false), + net_log_(job_net_log) { + if (!params_.resolver_proc) + params_.resolver_proc = HostResolverProc::GetDefault(); + // If default is unset, use the system proc. + if (!params_.resolver_proc) + params_.resolver_proc = new CallSystemHostResolverProc(); + } + + void Start() { + DCHECK(origin_loop_->BelongsToCurrentThread()); + net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); + StartLookupAttempt(); + } + + // Cancels this ProcTask. It will be orphaned. Any outstanding resolve + // attempts running on worker threads will continue running. Only once all the + // attempts complete will the final reference to this ProcTask be released. + void Cancel() { + DCHECK(origin_loop_->BelongsToCurrentThread()); + + if (was_canceled() || was_completed()) + return; + + callback_.Reset(); + net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); + } + + void set_had_non_speculative_request() { + DCHECK(origin_loop_->BelongsToCurrentThread()); + had_non_speculative_request_ = true; + } + + bool was_canceled() const { + DCHECK(origin_loop_->BelongsToCurrentThread()); + return callback_.is_null(); + } + + bool was_completed() const { + DCHECK(origin_loop_->BelongsToCurrentThread()); + return completed_attempt_number_ > 0; + } + + private: + friend class base::RefCountedThreadSafe; + ~ProcTask() {} + + void StartLookupAttempt() { + DCHECK(origin_loop_->BelongsToCurrentThread()); + base::TimeTicks start_time = base::TimeTicks::Now(); + ++attempt_number_; + // Dispatch the lookup attempt to a worker thread. + if (!base::WorkerPool::PostTask( + FROM_HERE, + base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), + 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). + origin_loop_->PostTask( + FROM_HERE, + base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), + start_time, attempt_number_, ERR_UNEXPECTED, 0)); + return; + } + + net_log_.AddEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_STARTED, + NetLog::IntegerCallback("attempt_number", attempt_number_)); + + // If we don't get the results within a given time, RetryIfNotComplete + // will start a new attempt on a different worker thread if none of our + // outstanding attempts have completed yet. + if (attempt_number_ <= params_.max_retry_attempts) { + origin_loop_->PostDelayedTask( + FROM_HERE, + base::Bind(&ProcTask::RetryIfNotComplete, this), + params_.unresponsive_delay); + } + } + + // WARNING: This code runs inside a worker pool. The shutdown code cannot + // wait for it to finish, so we must be very careful here about using other + // objects (like MessageLoops, Singletons, etc). During shutdown these objects + // may no longer exist. Multiple DoLookups() could be running in parallel, so + // any state inside of |this| must not mutate . + void DoLookup(const base::TimeTicks& start_time, + const uint32 attempt_number) { + AddressList results; + int os_error = 0; + // Running on the worker thread + int error = params_.resolver_proc->Resolve(key_.hostname, + key_.address_family, + key_.host_resolver_flags, + &results, + &os_error); + + origin_loop_->PostTask( + FROM_HERE, + base::Bind(&ProcTask::OnLookupComplete, this, results, start_time, + attempt_number, error, os_error)); + } + + // Makes next attempt if DoLookup() has not finished (runs on origin thread). + void RetryIfNotComplete() { + DCHECK(origin_loop_->BelongsToCurrentThread()); + + if (was_completed() || was_canceled()) + return; + + params_.unresponsive_delay *= params_.retry_factor; + StartLookupAttempt(); + } + + // Callback for when DoLookup() completes (runs on origin thread). + void OnLookupComplete(const AddressList& results, + const base::TimeTicks& start_time, + const uint32 attempt_number, + int error, + const int os_error) { + DCHECK(origin_loop_->BelongsToCurrentThread()); + DCHECK(error || !results.empty()); + + bool was_retry_attempt = attempt_number > 1; + + // Ideally the following code would be part of host_resolver_proc.cc, + // however it isn't safe to call NetworkChangeNotifier from worker threads. + // So we do it here on the IO thread instead. + if (error != OK && NetworkChangeNotifier::IsOffline()) + error = ERR_INTERNET_DISCONNECTED; + + // If this is the first attempt that is finishing later, then record data + // for the first attempt. Won't contaminate with retry attempt's data. + if (!was_retry_attempt) + RecordPerformanceHistograms(start_time, error, os_error); + + RecordAttemptHistograms(start_time, attempt_number, error, os_error); + + if (was_canceled()) + return; + + NetLog::ParametersCallback net_log_callback; + if (error != OK) { + net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, + attempt_number, + error, + os_error); + } else { + net_log_callback = NetLog::IntegerCallback("attempt_number", + attempt_number); + } + net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_ATTEMPT_FINISHED, + net_log_callback); + + if (was_completed()) + return; + + // Copy the results from the first worker thread that resolves the host. + results_ = results; + completed_attempt_number_ = attempt_number; + completed_attempt_error_ = error; + + if (was_retry_attempt) { + // If retry attempt finishes before 1st attempt, then get stats on how + // much time is saved by having spawned an extra attempt. + retry_attempt_finished_time_ = base::TimeTicks::Now(); + } + + if (error != OK) { + net_log_callback = base::Bind(&NetLogProcTaskFailedCallback, + 0, error, os_error); + } else { + net_log_callback = results_.CreateNetLogCallback(); + } + net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK, + net_log_callback); + + callback_.Run(error, results_); + } + + void RecordPerformanceHistograms(const base::TimeTicks& start_time, + const int error, + const int os_error) const { + DCHECK(origin_loop_->BelongsToCurrentThread()); + enum Category { // Used in HISTOGRAM_ENUMERATION. + RESOLVE_SUCCESS, + RESOLVE_FAIL, + RESOLVE_SPECULATIVE_SUCCESS, + RESOLVE_SPECULATIVE_FAIL, + RESOLVE_MAX, // Bounding value. + }; + int category = RESOLVE_MAX; // Illegal value for later DCHECK only. + + base::TimeDelta duration = base::TimeTicks::Now() - start_time; + if (error == OK) { + if (had_non_speculative_request_) { + category = RESOLVE_SUCCESS; + DNS_HISTOGRAM("DNS.ResolveSuccess", duration); + } else { + category = RESOLVE_SPECULATIVE_SUCCESS; + DNS_HISTOGRAM("DNS.ResolveSpeculativeSuccess", duration); + } + + // Log DNS lookups based on |address_family|. This will help us determine + // if IPv4 or IPv4/6 lookups are faster or slower. + switch(key_.address_family) { + case ADDRESS_FAMILY_IPV4: + DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV4", duration); + break; + case ADDRESS_FAMILY_IPV6: + DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_IPV6", duration); + break; + case ADDRESS_FAMILY_UNSPECIFIED: + DNS_HISTOGRAM("DNS.ResolveSuccess_FAMILY_UNSPEC", duration); + break; + } + } else { + if (had_non_speculative_request_) { + category = RESOLVE_FAIL; + DNS_HISTOGRAM("DNS.ResolveFail", duration); + } else { + category = RESOLVE_SPECULATIVE_FAIL; + DNS_HISTOGRAM("DNS.ResolveSpeculativeFail", duration); + } + // Log DNS lookups based on |address_family|. This will help us determine + // if IPv4 or IPv4/6 lookups are faster or slower. + switch(key_.address_family) { + case ADDRESS_FAMILY_IPV4: + DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV4", duration); + break; + case ADDRESS_FAMILY_IPV6: + DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_IPV6", duration); + break; + case ADDRESS_FAMILY_UNSPECIFIED: + DNS_HISTOGRAM("DNS.ResolveFail_FAMILY_UNSPEC", duration); + break; + } + UMA_HISTOGRAM_CUSTOM_ENUMERATION(kOSErrorsForGetAddrinfoHistogramName, + std::abs(os_error), + GetAllGetAddrinfoOSErrors()); + } + DCHECK_LT(category, static_cast(RESOLVE_MAX)); // Be sure it was set. + + UMA_HISTOGRAM_ENUMERATION("DNS.ResolveCategory", category, RESOLVE_MAX); + + static const bool show_parallelism_experiment_histograms = + base::FieldTrialList::TrialExists("DnsParallelism"); + if (show_parallelism_experiment_histograms) { + UMA_HISTOGRAM_ENUMERATION( + base::FieldTrial::MakeName("DNS.ResolveCategory", "DnsParallelism"), + category, RESOLVE_MAX); + if (RESOLVE_SUCCESS == category) { + DNS_HISTOGRAM(base::FieldTrial::MakeName("DNS.ResolveSuccess", + "DnsParallelism"), duration); + } + } + } + + void RecordAttemptHistograms(const base::TimeTicks& start_time, + const uint32 attempt_number, + const int error, + const int os_error) const { + DCHECK(origin_loop_->BelongsToCurrentThread()); + bool first_attempt_to_complete = + completed_attempt_number_ == attempt_number; + bool is_first_attempt = (attempt_number == 1); + + if (first_attempt_to_complete) { + // If this was first attempt to complete, then record the resolution + // status of the attempt. + if (completed_attempt_error_ == OK) { + UMA_HISTOGRAM_ENUMERATION( + "DNS.AttemptFirstSuccess", attempt_number, 100); + } else { + UMA_HISTOGRAM_ENUMERATION( + "DNS.AttemptFirstFailure", attempt_number, 100); + } + } + + if (error == OK) + UMA_HISTOGRAM_ENUMERATION("DNS.AttemptSuccess", attempt_number, 100); + else + UMA_HISTOGRAM_ENUMERATION("DNS.AttemptFailure", attempt_number, 100); + + // If first attempt didn't finish before retry attempt, then calculate stats + // on how much time is saved by having spawned an extra attempt. + if (!first_attempt_to_complete && is_first_attempt && !was_canceled()) { + DNS_HISTOGRAM("DNS.AttemptTimeSavedByRetry", + base::TimeTicks::Now() - retry_attempt_finished_time_); + } + + if (was_canceled() || !first_attempt_to_complete) { + // Count those attempts which completed after the job was already canceled + // OR after the job was already completed by an earlier attempt (so in + // effect). + UMA_HISTOGRAM_ENUMERATION("DNS.AttemptDiscarded", attempt_number, 100); + + // Record if job is canceled. + if (was_canceled()) + UMA_HISTOGRAM_ENUMERATION("DNS.AttemptCancelled", attempt_number, 100); + } + + base::TimeDelta duration = base::TimeTicks::Now() - start_time; + if (error == OK) + DNS_HISTOGRAM("DNS.AttemptSuccessDuration", duration); + else + DNS_HISTOGRAM("DNS.AttemptFailDuration", duration); + } + + // Set on the origin thread, read on the worker thread. + Key key_; + + // Holds 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. + ProcTaskParams params_; + + // The listener to the results of this ProcTask. + Callback callback_; + + // Used to post ourselves onto the origin thread. + scoped_refptr origin_loop_; + + // Keeps track of the number of attempts we have made so far to resolve the + // host. Whenever we start an attempt to resolve the host, we increase this + // number. + uint32 attempt_number_; + + // The index of the attempt which finished first (or 0 if the job is still in + // progress). + uint32 completed_attempt_number_; + + // The result (a net error code) from the first attempt to complete. + int completed_attempt_error_; + + // The time when retry attempt was finished. + base::TimeTicks retry_attempt_finished_time_; + + // True if a non-speculative request was ever attached to this job + // (regardless of whether or not it was later canceled. + // This boolean is used for histogramming the duration of jobs used to + // service non-speculative requests. + bool had_non_speculative_request_; + + AddressList results_; + + BoundNetLog net_log_; + + DISALLOW_COPY_AND_ASSIGN(ProcTask); +}; + +//----------------------------------------------------------------------------- + +// Wraps a call to TestIPv6Support to be executed on the WorkerPool as it takes +// 40-100ms. +class HostResolverImpl::IPv6ProbeJob { + public: + IPv6ProbeJob(const base::WeakPtr& resolver, NetLog* net_log) + : resolver_(resolver), + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_IPV6_PROBE_JOB)), + result_(false, IPV6_SUPPORT_MAX, OK) { + DCHECK(resolver); + net_log_.BeginEvent(NetLog::TYPE_IPV6_PROBE_RUNNING); + const bool kIsSlow = true; + base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&IPv6ProbeJob::DoProbe, base::Unretained(this)), + base::Bind(&IPv6ProbeJob::OnProbeComplete, base::Owned(this)), + kIsSlow); + } + + virtual ~IPv6ProbeJob() {} + + private: + // Runs on worker thread. + void DoProbe() { + result_ = TestIPv6Support(); + } + + void OnProbeComplete() { + net_log_.EndEvent(NetLog::TYPE_IPV6_PROBE_RUNNING, + base::Bind(&IPv6SupportResult::ToNetLogValue, + base::Unretained(&result_))); + if (!resolver_) + return; + resolver_->IPv6ProbeSetDefaultAddressFamily( + result_.ipv6_supported ? ADDRESS_FAMILY_UNSPECIFIED + : ADDRESS_FAMILY_IPV4); + } + + // Used/set only on origin thread. + base::WeakPtr resolver_; + + BoundNetLog net_log_; + + IPv6SupportResult result_; + + DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); +}; + +// Wraps a call to HaveOnlyLoopbackAddresses to be executed on the WorkerPool as +// it takes 40-100ms and should not block initialization. +class HostResolverImpl::LoopbackProbeJob { + public: + explicit LoopbackProbeJob(const base::WeakPtr& resolver) + : resolver_(resolver), + result_(false) { + DCHECK(resolver); + const bool kIsSlow = true; + base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&LoopbackProbeJob::DoProbe, base::Unretained(this)), + base::Bind(&LoopbackProbeJob::OnProbeComplete, base::Owned(this)), + kIsSlow); + } + + virtual ~LoopbackProbeJob() {} + + private: + // Runs on worker thread. + void DoProbe() { + result_ = HaveOnlyLoopbackAddresses(); + } + + void OnProbeComplete() { + if (!resolver_) + return; + resolver_->SetHaveOnlyLoopbackAddresses(result_); + } + + // Used/set only on origin thread. + base::WeakPtr resolver_; + + bool result_; + + DISALLOW_COPY_AND_ASSIGN(LoopbackProbeJob); +}; + +//----------------------------------------------------------------------------- + +// Resolves the hostname using DnsTransaction. +// TODO(szym): This could be moved to separate source file as well. +class HostResolverImpl::DnsTask : public base::SupportsWeakPtr { + public: + typedef base::Callback Callback; + + DnsTask(DnsClient* client, + const Key& key, + const Callback& callback, + const BoundNetLog& job_net_log) + : client_(client), + family_(key.address_family), + callback_(callback), + net_log_(job_net_log) { + DCHECK(client); + DCHECK(!callback.is_null()); + + // If unspecified, do IPv4 first, because suffix search will be faster. + uint16 qtype = (family_ == ADDRESS_FAMILY_IPV6) ? + dns_protocol::kTypeAAAA : + dns_protocol::kTypeA; + transaction_ = client_->GetTransactionFactory()->CreateTransaction( + key.hostname, + qtype, + base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), + true /* first_query */, base::TimeTicks::Now()), + net_log_); + } + + int Start() { + net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK); + return transaction_->Start(); + } + + private: + void OnTransactionComplete(bool first_query, + const base::TimeTicks& start_time, + DnsTransaction* transaction, + int net_error, + const DnsResponse* response) { + DCHECK(transaction); + base::TimeDelta duration = base::TimeTicks::Now() - start_time; + // Run |callback_| last since the owning Job will then delete this DnsTask. + if (net_error != OK) { + DNS_HISTOGRAM("AsyncDNS.TransactionFailure", duration); + OnFailure(net_error, DnsResponse::DNS_PARSE_OK); + return; + } + + CHECK(response); + DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", duration); + switch (transaction->GetType()) { + case dns_protocol::kTypeA: + DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_A", duration); + break; + case dns_protocol::kTypeAAAA: + DNS_HISTOGRAM("AsyncDNS.TransactionSuccess_AAAA", duration); + break; + } + AddressList addr_list; + base::TimeDelta ttl; + DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); + UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", + result, + DnsResponse::DNS_PARSE_RESULT_MAX); + if (result != DnsResponse::DNS_PARSE_OK) { + // Fail even if the other query succeeds. + OnFailure(ERR_DNS_MALFORMED_RESPONSE, result); + return; + } + + bool needs_sort = false; + if (first_query) { + DCHECK(client_->GetConfig()) << + "Transaction should have been aborted when config changed!"; + if (family_ == ADDRESS_FAMILY_IPV6) { + needs_sort = (addr_list.size() > 1); + } else if (family_ == ADDRESS_FAMILY_UNSPECIFIED) { + first_addr_list_ = addr_list; + first_ttl_ = ttl; + // Use fully-qualified domain name to avoid search. + transaction_ = client_->GetTransactionFactory()->CreateTransaction( + response->GetDottedName() + ".", + dns_protocol::kTypeAAAA, + base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), + false /* first_query */, base::TimeTicks::Now()), + net_log_); + net_error = transaction_->Start(); + if (net_error != ERR_IO_PENDING) + OnFailure(net_error, DnsResponse::DNS_PARSE_OK); + return; + } + } else { + DCHECK_EQ(ADDRESS_FAMILY_UNSPECIFIED, family_); + bool has_ipv6_addresses = !addr_list.empty(); + if (!first_addr_list_.empty()) { + ttl = std::min(ttl, first_ttl_); + // Place IPv4 addresses after IPv6. + addr_list.insert(addr_list.end(), first_addr_list_.begin(), + first_addr_list_.end()); + } + needs_sort = (has_ipv6_addresses && addr_list.size() > 1); + } + + if (addr_list.empty()) { + // TODO(szym): Don't fallback to ProcTask in this case. + OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); + return; + } + + if (needs_sort) { + // Sort could complete synchronously. + client_->GetAddressSorter()->Sort( + addr_list, + base::Bind(&DnsTask::OnSortComplete, + AsWeakPtr(), + base::TimeTicks::Now(), + ttl)); + } else { + OnSuccess(addr_list, ttl); + } + } + + void OnSortComplete(base::TimeTicks start_time, + base::TimeDelta ttl, + bool success, + const AddressList& addr_list) { + if (!success) { + DNS_HISTOGRAM("AsyncDNS.SortFailure", + base::TimeTicks::Now() - start_time); + OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK); + return; + } + + DNS_HISTOGRAM("AsyncDNS.SortSuccess", + base::TimeTicks::Now() - start_time); + + // AddressSorter prunes unusable destinations. + if (addr_list.empty()) { + LOG(WARNING) << "Address list empty after RFC3484 sort"; + OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); + return; + } + + OnSuccess(addr_list, ttl); + } + + void OnFailure(int net_error, DnsResponse::Result result) { + DCHECK_NE(OK, net_error); + net_log_.EndEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, + base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); + callback_.Run(net_error, AddressList(), base::TimeDelta()); + } + + void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) { + net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, + addr_list.CreateNetLogCallback()); + callback_.Run(OK, addr_list, ttl); + } + + DnsClient* client_; + AddressFamily family_; + // The listener to the results of this DnsTask. + Callback callback_; + const BoundNetLog net_log_; + + scoped_ptr transaction_; + + // Results from the first transaction. Used only if |family_| is unspecified. + AddressList first_addr_list_; + base::TimeDelta first_ttl_; + + DISALLOW_COPY_AND_ASSIGN(DnsTask); +}; + +//----------------------------------------------------------------------------- + +// Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. +class HostResolverImpl::Job : public PrioritizedDispatcher::Job { + public: + // Creates new job for |key| where |request_net_log| is bound to the + // request that spawned it. + Job(const base::WeakPtr& resolver, + const Key& key, + RequestPriority priority, + const BoundNetLog& request_net_log) + : resolver_(resolver), + key_(key), + priority_tracker_(priority), + had_non_speculative_request_(false), + had_dns_config_(false), + dns_task_error_(OK), + creation_time_(base::TimeTicks::Now()), + priority_change_time_(creation_time_), + net_log_(BoundNetLog::Make(request_net_log.net_log(), + NetLog::SOURCE_HOST_RESOLVER_IMPL_JOB)) { + request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CREATE_JOB); + + net_log_.BeginEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, + base::Bind(&NetLogJobCreationCallback, + request_net_log.source(), + &key_.hostname)); + } + + virtual ~Job() { + if (is_running()) { + // |resolver_| was destroyed with this Job still in flight. + // Clean-up, record in the log, but don't run any callbacks. + if (is_proc_running()) { + proc_task_->Cancel(); + proc_task_ = NULL; + } + // Clean up now for nice NetLog. + dns_task_.reset(NULL); + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, + ERR_ABORTED); + } else if (is_queued()) { + // |resolver_| was destroyed without running this Job. + // TODO(szym): is there any benefit in having this distinction? + net_log_.AddEvent(NetLog::TYPE_CANCELLED); + net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB); + } + // else CompleteRequests logged EndEvent. + + // Log any remaining Requests as cancelled. + for (RequestsList::const_iterator it = requests_.begin(); + it != requests_.end(); ++it) { + Request* req = *it; + if (req->was_canceled()) + continue; + DCHECK_EQ(this, req->job()); + LogCancelRequest(req->source_net_log(), req->request_net_log(), + req->info()); + } + } + + // Add this job to the dispatcher. + void Schedule() { + handle_ = resolver_->dispatcher_.Add(this, priority()); + } + + void AddRequest(scoped_ptr req) { + DCHECK_EQ(key_.hostname, req->info().hostname()); + + req->set_job(this); + priority_tracker_.Add(req->info().priority()); + + req->request_net_log().AddEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_ATTACH, + net_log_.source().ToEventParametersCallback()); + + net_log_.AddEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_ATTACH, + base::Bind(&NetLogJobAttachCallback, + req->request_net_log().source(), + priority())); + + // TODO(szym): Check if this is still needed. + if (!req->info().is_speculative()) { + had_non_speculative_request_ = true; + if (proc_task_) + proc_task_->set_had_non_speculative_request(); + } + + requests_.push_back(req.release()); + + UpdatePriority(); + } + + // Marks |req| as cancelled. If it was the last active Request, also finishes + // this Job, marking it as cancelled, and deletes it. + void CancelRequest(Request* req) { + DCHECK_EQ(key_.hostname, req->info().hostname()); + DCHECK(!req->was_canceled()); + + // Don't remove it from |requests_| just mark it canceled. + req->MarkAsCanceled(); + LogCancelRequest(req->source_net_log(), req->request_net_log(), + req->info()); + + priority_tracker_.Remove(req->info().priority()); + net_log_.AddEvent( + NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_REQUEST_DETACH, + base::Bind(&NetLogJobAttachCallback, + req->request_net_log().source(), + priority())); + + if (num_active_requests() > 0) { + UpdatePriority(); + } else { + // If we were called from a Request's callback within CompleteRequests, + // that Request could not have been cancelled, so num_active_requests() + // could not be 0. Therefore, we are not in CompleteRequests(). + CompleteRequestsWithError(OK /* cancelled */); + } + } + + // Called from AbortAllInProgressJobs. Completes all requests and destroys + // the job. This currently assumes the abort is due to a network change. + void Abort() { + DCHECK(is_running()); + CompleteRequestsWithError(ERR_NETWORK_CHANGED); + } + + // If DnsTask present, abort it and fall back to ProcTask. + void AbortDnsTask() { + if (dns_task_) { + dns_task_.reset(); + dns_task_error_ = OK; + StartProcTask(); + } + } + + // Called by HostResolverImpl when this job is evicted due to queue overflow. + // Completes all requests and destroys the job. + void OnEvicted() { + DCHECK(!is_running()); + DCHECK(is_queued()); + handle_.Reset(); + + net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); + + // This signals to CompleteRequests that this job never ran. + CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); + } + + // Attempts to serve the job from HOSTS. Returns true if succeeded and + // this Job was destroyed. + bool ServeFromHosts() { + DCHECK_GT(num_active_requests(), 0u); + AddressList addr_list; + if (resolver_->ServeFromHosts(key(), + requests_.front()->info(), + &addr_list)) { + // This will destroy the Job. + CompleteRequests( + HostCache::Entry(OK, MakeAddressListForRequest(addr_list)), + base::TimeDelta()); + return true; + } + return false; + } + + const Key key() const { + return key_; + } + + bool is_queued() const { + return !handle_.is_null(); + } + + bool is_running() const { + return is_dns_running() || is_proc_running(); + } + + private: + void UpdatePriority() { + if (is_queued()) { + if (priority() != static_cast(handle_.priority())) + priority_change_time_ = base::TimeTicks::Now(); + handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); + } + } + + AddressList MakeAddressListForRequest(const AddressList& list) const { + if (requests_.empty()) + return list; + return AddressList::CopyWithPort(list, requests_.front()->info().port()); + } + + // PriorityDispatch::Job: + virtual void Start() OVERRIDE { + DCHECK(!is_running()); + handle_.Reset(); + + net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_STARTED); + + had_dns_config_ = resolver_->HaveDnsConfig(); + + base::TimeTicks now = base::TimeTicks::Now(); + base::TimeDelta queue_time = now - creation_time_; + base::TimeDelta queue_time_after_change = now - priority_change_time_; + + if (had_dns_config_) { + DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTime", priority(), + queue_time); + DNS_HISTOGRAM_BY_PRIORITY("AsyncDNS.JobQueueTimeAfterChange", priority(), + queue_time_after_change); + } else { + DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTime", priority(), queue_time); + DNS_HISTOGRAM_BY_PRIORITY("DNS.JobQueueTimeAfterChange", priority(), + queue_time_after_change); + } + + // Caution: Job::Start must not complete synchronously. + if (had_dns_config_ && !ResemblesMulticastDNSName(key_.hostname)) { + StartDnsTask(); + } else { + StartProcTask(); + } + } + + // TODO(szym): Since DnsTransaction does not consume threads, we can increase + // the limits on |dispatcher_|. But in order to keep the number of WorkerPool + // threads low, we will need to use an "inner" PrioritizedDispatcher with + // tighter limits. + void StartProcTask() { + DCHECK(!is_dns_running()); + proc_task_ = new ProcTask( + key_, + resolver_->proc_params_, + base::Bind(&Job::OnProcTaskComplete, base::Unretained(this), + base::TimeTicks::Now()), + net_log_); + + if (had_non_speculative_request_) + proc_task_->set_had_non_speculative_request(); + // Start() could be called from within Resolve(), hence it must NOT directly + // call OnProcTaskComplete, for example, on synchronous failure. + proc_task_->Start(); + } + + // Called by ProcTask when it completes. + void OnProcTaskComplete(base::TimeTicks start_time, + int net_error, + const AddressList& addr_list) { + DCHECK(is_proc_running()); + + if (!resolver_->resolved_known_ipv6_hostname_ && + net_error == OK && + key_.address_family == ADDRESS_FAMILY_UNSPECIFIED) { + if (key_.hostname == "www.google.com") { + resolver_->resolved_known_ipv6_hostname_ = true; + bool got_ipv6_address = false; + for (size_t i = 0; i < addr_list.size(); ++i) { + if (addr_list[i].GetFamily() == ADDRESS_FAMILY_IPV6) + got_ipv6_address = true; + } + UMA_HISTOGRAM_BOOLEAN("Net.UnspecResolvedIPv6", got_ipv6_address); + } + } + + if (dns_task_error_ != OK) { + base::TimeDelta duration = base::TimeTicks::Now() - start_time; + if (net_error == OK) { + DNS_HISTOGRAM("AsyncDNS.FallbackSuccess", duration); + if ((dns_task_error_ == ERR_NAME_NOT_RESOLVED) && + ResemblesNetBIOSName(key_.hostname)) { + UmaAsyncDnsResolveStatus(RESOLVE_STATUS_SUSPECT_NETBIOS); + } else { + UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); + } + UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", + std::abs(dns_task_error_), + GetAllErrorCodesForUma()); + resolver_->OnDnsTaskResolve(dns_task_error_); + } else { + DNS_HISTOGRAM("AsyncDNS.FallbackFail", duration); + UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); + } + } + + base::TimeDelta ttl = + base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds); + if (net_error == OK) + ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); + + // Don't store the |ttl| in cache since it's not obtained from the server. + CompleteRequests( + HostCache::Entry(net_error, MakeAddressListForRequest(addr_list)), + ttl); + } + + void StartDnsTask() { + DCHECK(resolver_->HaveDnsConfig()); + dns_task_.reset(new DnsTask( + resolver_->dns_client_.get(), + key_, + base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this), + base::TimeTicks::Now()), + net_log_)); + + int rv = dns_task_->Start(); + if (rv != ERR_IO_PENDING) { + DCHECK_NE(OK, rv); + dns_task_error_ = rv; + dns_task_.reset(); + StartProcTask(); + } + } + + // Called by DnsTask when it completes. + void OnDnsTaskComplete(base::TimeTicks start_time, + int net_error, + const AddressList& addr_list, + base::TimeDelta ttl) { + DCHECK(is_dns_running()); + + base::TimeDelta duration = base::TimeTicks::Now() - start_time; + if (net_error != OK) { + DNS_HISTOGRAM("AsyncDNS.ResolveFail", duration); + + dns_task_error_ = net_error; + dns_task_.reset(); + + // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. + // http://crbug.com/117655 + + // TODO(szym): Some net errors indicate lack of connectivity. Starting + // ProcTask in that case is a waste of time. + StartProcTask(); + return; + } + DNS_HISTOGRAM("AsyncDNS.ResolveSuccess", duration); + // Log DNS lookups based on |address_family|. + switch(key_.address_family) { + case ADDRESS_FAMILY_IPV4: + DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV4", duration); + break; + case ADDRESS_FAMILY_IPV6: + DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_IPV6", duration); + break; + case ADDRESS_FAMILY_UNSPECIFIED: + DNS_HISTOGRAM("AsyncDNS.ResolveSuccess_FAMILY_UNSPEC", duration); + break; + } + + UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); + RecordTTL(ttl); + + resolver_->OnDnsTaskResolve(OK); + + base::TimeDelta bounded_ttl = + std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds)); + + CompleteRequests( + HostCache::Entry(net_error, MakeAddressListForRequest(addr_list), ttl), + bounded_ttl); + } + + // Performs Job's last rites. Completes all Requests. Deletes this. + void CompleteRequests(const HostCache::Entry& entry, + base::TimeDelta ttl) { + CHECK(resolver_); + + // This job must be removed from resolver's |jobs_| now to make room for a + // new job with the same key in case one of the OnComplete callbacks decides + // to spawn one. Consequently, the job deletes itself when CompleteRequests + // is done. + scoped_ptr self_deleter(this); + + resolver_->RemoveJob(this); + + if (is_running()) { + DCHECK(!is_queued()); + if (is_proc_running()) { + proc_task_->Cancel(); + proc_task_ = NULL; + } + dns_task_.reset(); + + // Signal dispatcher that a slot has opened. + resolver_->dispatcher_.OnJobFinished(); + } else if (is_queued()) { + resolver_->dispatcher_.Cancel(handle_); + handle_.Reset(); + } + + if (num_active_requests() == 0) { + net_log_.AddEvent(NetLog::TYPE_CANCELLED); + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, + OK); + return; + } + + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, + entry.error); + + DCHECK(!requests_.empty()); + + if (entry.error == OK) { + // Record this histogram here, when we know the system has a valid DNS + // configuration. + UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", + resolver_->received_dns_config_); + } + + bool did_complete = (entry.error != ERR_NETWORK_CHANGED) && + (entry.error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); + if (did_complete) + resolver_->CacheResult(key_, entry, ttl); + + // Complete all of the requests that were attached to the job. + for (RequestsList::const_iterator it = requests_.begin(); + it != requests_.end(); ++it) { + Request* req = *it; + + if (req->was_canceled()) + continue; + + DCHECK_EQ(this, req->job()); + // Update the net log and notify registered observers. + LogFinishRequest(req->source_net_log(), req->request_net_log(), + req->info(), entry.error); + if (did_complete) { + // Record effective total time from creation to completion. + RecordTotalTime(had_dns_config_, req->info().is_speculative(), + base::TimeTicks::Now() - req->request_time()); + } + req->OnComplete(entry.error, entry.addrlist); + + // Check if the resolver was destroyed as a result of running the + // callback. If it was, we could continue, but we choose to bail. + if (!resolver_) + return; + } + } + + // Convenience wrapper for CompleteRequests in case of failure. + void CompleteRequestsWithError(int net_error) { + CompleteRequests(HostCache::Entry(net_error, AddressList()), + base::TimeDelta()); + } + + RequestPriority priority() const { + return priority_tracker_.highest_priority(); + } + + // Number of non-canceled requests in |requests_|. + size_t num_active_requests() const { + return priority_tracker_.total_count(); + } + + bool is_dns_running() const { + return dns_task_.get() != NULL; + } + + bool is_proc_running() const { + return proc_task_.get() != NULL; + } + + base::WeakPtr resolver_; + + Key key_; + + // Tracks the highest priority across |requests_|. + PriorityTracker priority_tracker_; + + bool had_non_speculative_request_; + + // Distinguishes measurements taken while DnsClient was fully configured. + bool had_dns_config_; + + // Result of DnsTask. + int dns_task_error_; + + const base::TimeTicks creation_time_; + base::TimeTicks priority_change_time_; + + BoundNetLog net_log_; + + // Resolves the host using a HostResolverProc. + scoped_refptr proc_task_; + + // Resolves the host using a DnsTransaction. + scoped_ptr dns_task_; + + // All Requests waiting for the result of this Job. Some can be canceled. + RequestsList requests_; + + // A handle used in |HostResolverImpl::dispatcher_|. + PrioritizedDispatcher::Handle handle_; +}; + +//----------------------------------------------------------------------------- + +HostResolverImpl::ProcTaskParams::ProcTaskParams( + HostResolverProc* resolver_proc, + size_t max_retry_attempts) + : resolver_proc(resolver_proc), + max_retry_attempts(max_retry_attempts), + unresponsive_delay(base::TimeDelta::FromMilliseconds(6000)), + retry_factor(2) { +} + +HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} + +HostResolverImpl::HostResolverImpl( + scoped_ptr cache, + const PrioritizedDispatcher::Limits& job_limits, + const ProcTaskParams& proc_params, + NetLog* net_log) + : cache_(cache.Pass()), + dispatcher_(job_limits), + max_queued_jobs_(job_limits.total_jobs * 100u), + proc_params_(proc_params), + net_log_(net_log), + default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), + weak_ptr_factory_(this), + probe_weak_ptr_factory_(this), + received_dns_config_(false), + num_dns_failures_(0), + ipv6_probe_monitoring_(false), + resolved_known_ipv6_hostname_(false), + additional_resolver_flags_(0) { + + DCHECK_GE(dispatcher_.num_priorities(), static_cast(NUM_PRIORITIES)); + + // Maximum of 4 retry attempts for host resolution. + static const size_t kDefaultMaxRetryAttempts = 4u; + + if (proc_params_.max_retry_attempts == HostResolver::kDefaultRetryAttempts) + proc_params_.max_retry_attempts = kDefaultMaxRetryAttempts; + +#if defined(OS_WIN) + EnsureWinsockInit(); +#endif +#if defined(OS_POSIX) && !defined(OS_MACOSX) + new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr()); +#endif + NetworkChangeNotifier::AddIPAddressObserver(this); + NetworkChangeNotifier::AddDNSObserver(this); +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ + !defined(OS_ANDROID) + EnsureDnsReloaderInit(); +#endif + + // TODO(szym): Remove when received_dns_config_ is removed, once + // http://crbug.com/137914 is resolved. + { + DnsConfig dns_config; + NetworkChangeNotifier::GetDnsConfig(&dns_config); + received_dns_config_ = dns_config.IsValid(); + } +} + +HostResolverImpl::~HostResolverImpl() { + // This will also cancel all outstanding requests. + STLDeleteValues(&jobs_); + + NetworkChangeNotifier::RemoveIPAddressObserver(this); + NetworkChangeNotifier::RemoveDNSObserver(this); +} + +void HostResolverImpl::SetMaxQueuedJobs(size_t value) { + DCHECK_EQ(0u, dispatcher_.num_queued_jobs()); + DCHECK_GT(value, 0u); + max_queued_jobs_ = value; +} + +int HostResolverImpl::Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& source_net_log) { + DCHECK(addresses); + DCHECK(CalledOnValidThread()); + DCHECK_EQ(false, callback.is_null()); + + // Make a log item for the request. + BoundNetLog request_net_log = BoundNetLog::Make(net_log_, + NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); + + LogStartRequest(source_net_log, request_net_log, info); + + // Build a key that identifies the request in the cache and in the + // outstanding jobs map. + Key key = GetEffectiveKeyForRequest(info); + + int rv = ResolveHelper(key, info, addresses, request_net_log); + if (rv != ERR_DNS_CACHE_MISS) { + LogFinishRequest(source_net_log, request_net_log, info, rv); + RecordTotalTime(HaveDnsConfig(), info.is_speculative(), base::TimeDelta()); + return rv; + } + + // Next we need to attach our request to a "job". This job is responsible for + // calling "getaddrinfo(hostname)" on a worker thread. + + JobMap::iterator jobit = jobs_.find(key); + Job* job; + if (jobit == jobs_.end()) { + job = new Job(weak_ptr_factory_.GetWeakPtr(), key, info.priority(), + request_net_log); + job->Schedule(); + + // Check for queue overflow. + if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { + Job* evicted = static_cast(dispatcher_.EvictOldestLowest()); + DCHECK(evicted); + evicted->OnEvicted(); // Deletes |evicted|. + if (evicted == job) { + rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; + LogFinishRequest(source_net_log, request_net_log, info, rv); + return rv; + } + } + jobs_.insert(jobit, std::make_pair(key, job)); + } else { + job = jobit->second; + } + + // Can't complete synchronously. Create and attach request. + scoped_ptr req(new Request(source_net_log, + request_net_log, + info, + callback, + addresses)); + if (out_req) + *out_req = reinterpret_cast(req.get()); + + job->AddRequest(req.Pass()); + // Completion happens during Job::CompleteRequests(). + return ERR_IO_PENDING; +} + +int HostResolverImpl::ResolveHelper(const Key& key, + const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& request_net_log) { + // The result of |getaddrinfo| for empty hosts is inconsistent across systems. + // On Windows it gives the default interface's address, whereas on Linux it + // gives an error. We will make it fail on all platforms for consistency. + if (info.hostname().empty() || info.hostname().size() > kMaxHostLength) + return ERR_NAME_NOT_RESOLVED; + + int net_error = ERR_UNEXPECTED; + if (ResolveAsIP(key, info, &net_error, addresses)) + return net_error; + if (ServeFromCache(key, info, &net_error, addresses)) { + request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT); + return net_error; + } + // TODO(szym): Do not do this if nsswitch.conf instructs not to. + // http://crbug.com/117655 + if (ServeFromHosts(key, info, addresses)) { + request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_HOSTS_HIT); + return OK; + } + return ERR_DNS_CACHE_MISS; +} + +int HostResolverImpl::ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& source_net_log) { + DCHECK(CalledOnValidThread()); + DCHECK(addresses); + + // Make a log item for the request. + BoundNetLog request_net_log = BoundNetLog::Make(net_log_, + NetLog::SOURCE_HOST_RESOLVER_IMPL_REQUEST); + + // Update the net log and notify registered observers. + LogStartRequest(source_net_log, request_net_log, info); + + Key key = GetEffectiveKeyForRequest(info); + + int rv = ResolveHelper(key, info, addresses, request_net_log); + LogFinishRequest(source_net_log, request_net_log, info, rv); + return rv; +} + +void HostResolverImpl::CancelRequest(RequestHandle req_handle) { + DCHECK(CalledOnValidThread()); + Request* req = reinterpret_cast(req_handle); + DCHECK(req); + Job* job = req->job(); + DCHECK(job); + job->CancelRequest(req); +} + +void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { + DCHECK(CalledOnValidThread()); + default_address_family_ = address_family; + ipv6_probe_monitoring_ = false; +} + +AddressFamily HostResolverImpl::GetDefaultAddressFamily() const { + return default_address_family_; +} + +void HostResolverImpl::ProbeIPv6Support() { + DCHECK(CalledOnValidThread()); + DCHECK(!ipv6_probe_monitoring_); + ipv6_probe_monitoring_ = true; + OnIPAddressChanged(); +} + +void HostResolverImpl::SetDnsClientEnabled(bool enabled) { + DCHECK(CalledOnValidThread()); +#if defined(ENABLE_BUILT_IN_DNS) + if (enabled && !dns_client_) { + SetDnsClient(DnsClient::CreateClient(net_log_)); + } else if (!enabled && dns_client_) { + SetDnsClient(scoped_ptr()); + } +#endif +} + +HostCache* HostResolverImpl::GetHostCache() { + return cache_.get(); +} + +base::Value* HostResolverImpl::GetDnsConfigAsValue() const { + // Check if async DNS is disabled. + if (!dns_client_.get()) + return NULL; + + // Check if async DNS is enabled, but we currently have no configuration + // for it. + const DnsConfig* dns_config = dns_client_->GetConfig(); + if (dns_config == NULL) + return new DictionaryValue(); + + return dns_config->ToValue(); +} + +bool HostResolverImpl::ResolveAsIP(const Key& key, + const RequestInfo& info, + int* net_error, + AddressList* addresses) { + DCHECK(addresses); + DCHECK(net_error); + IPAddressNumber ip_number; + if (!ParseIPLiteralToNumber(key.hostname, &ip_number)) + return false; + + DCHECK_EQ(key.host_resolver_flags & + ~(HOST_RESOLVER_CANONNAME | HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6), + 0) << " Unhandled flag"; + bool ipv6_disabled = (default_address_family_ == ADDRESS_FAMILY_IPV4) && + !ipv6_probe_monitoring_; + *net_error = OK; + if ((ip_number.size() == kIPv6AddressSize) && ipv6_disabled) { + *net_error = ERR_NAME_NOT_RESOLVED; + } else { + *addresses = AddressList::CreateFromIPAddress(ip_number, info.port()); + if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME) + addresses->SetDefaultCanonicalName(); + } + return true; +} + +bool HostResolverImpl::ServeFromCache(const Key& key, + const RequestInfo& info, + int* net_error, + AddressList* addresses) { + DCHECK(addresses); + DCHECK(net_error); + if (!info.allow_cached_response() || !cache_.get()) + return false; + + const HostCache::Entry* cache_entry = cache_->Lookup( + key, base::TimeTicks::Now()); + if (!cache_entry) + return false; + + *net_error = cache_entry->error; + if (*net_error == OK) { + if (cache_entry->has_ttl()) + RecordTTL(cache_entry->ttl); + *addresses = EnsurePortOnAddressList(cache_entry->addrlist, info.port()); + } + return true; +} + +bool HostResolverImpl::ServeFromHosts(const Key& key, + const RequestInfo& info, + AddressList* addresses) { + DCHECK(addresses); + if (!HaveDnsConfig()) + return false; + + // HOSTS lookups are case-insensitive. + std::string hostname = StringToLowerASCII(key.hostname); + + // If |address_family| is ADDRESS_FAMILY_UNSPECIFIED other implementations + // (glibc and c-ares) return the first matching line. We have more + // flexibility, but lose implicit ordering. + // TODO(szym) http://crbug.com/117850 + const DnsHosts& hosts = dns_client_->GetConfig()->hosts; + DnsHosts::const_iterator it = hosts.find( + DnsHostsKey(hostname, + key.address_family == ADDRESS_FAMILY_UNSPECIFIED ? + ADDRESS_FAMILY_IPV4 : key.address_family)); + + if (it == hosts.end()) { + if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED) + return false; + + it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); + if (it == hosts.end()) + return false; + } + + *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); + return true; +} + +void HostResolverImpl::CacheResult(const Key& key, + const HostCache::Entry& entry, + base::TimeDelta ttl) { + if (cache_.get()) + cache_->Set(key, entry, base::TimeTicks::Now(), ttl); +} + +void HostResolverImpl::RemoveJob(Job* job) { + DCHECK(job); + JobMap::iterator it = jobs_.find(job->key()); + if (it != jobs_.end() && it->second == job) + jobs_.erase(it); +} + +void HostResolverImpl::IPv6ProbeSetDefaultAddressFamily( + AddressFamily address_family) { + DCHECK(address_family == ADDRESS_FAMILY_UNSPECIFIED || + address_family == ADDRESS_FAMILY_IPV4); + if (!ipv6_probe_monitoring_) + return; + if (default_address_family_ != address_family) { + VLOG(1) << "IPv6Probe forced AddressFamily setting to " + << ((address_family == ADDRESS_FAMILY_UNSPECIFIED) ? + "ADDRESS_FAMILY_UNSPECIFIED" : "ADDRESS_FAMILY_IPV4"); + } + default_address_family_ = address_family; +} + +void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) { + if (result) { + additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; + } else { + additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; + } +} + +HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( + const RequestInfo& info) const { + HostResolverFlags effective_flags = + info.host_resolver_flags() | additional_resolver_flags_; + AddressFamily effective_address_family = info.address_family(); + if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED && + default_address_family_ != ADDRESS_FAMILY_UNSPECIFIED) { + effective_address_family = default_address_family_; + if (ipv6_probe_monitoring_) + effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + } + return Key(info.hostname(), effective_address_family, effective_flags); +} + +void HostResolverImpl::AbortAllInProgressJobs() { + // In Abort, a Request callback could spawn new Jobs with matching keys, so + // first collect and remove all running jobs from |jobs_|. + ScopedVector jobs_to_abort; + for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { + Job* job = it->second; + if (job->is_running()) { + jobs_to_abort.push_back(job); + jobs_.erase(it++); + } else { + DCHECK(job->is_queued()); + ++it; + } + } + + // Check if no dispatcher slots leaked out. + DCHECK_EQ(dispatcher_.num_running_jobs(), jobs_to_abort.size()); + + // Life check to bail once |this| is deleted. + base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); + + // Then Abort them. + for (size_t i = 0; self && i < jobs_to_abort.size(); ++i) { + jobs_to_abort[i]->Abort(); + jobs_to_abort[i] = NULL; + } +} + +void HostResolverImpl::TryServingAllJobsFromHosts() { + if (!HaveDnsConfig()) + return; + + // TODO(szym): Do not do this if nsswitch.conf instructs not to. + // http://crbug.com/117655 + + // Life check to bail once |this| is deleted. + base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); + + for (JobMap::iterator it = jobs_.begin(); self && it != jobs_.end(); ) { + Job* job = it->second; + ++it; + // This could remove |job| from |jobs_|, but iterator will remain valid. + job->ServeFromHosts(); + } +} + +void HostResolverImpl::OnIPAddressChanged() { + resolved_known_ipv6_hostname_ = false; + // Abandon all ProbeJobs. + probe_weak_ptr_factory_.InvalidateWeakPtrs(); + if (cache_.get()) + cache_->clear(); + if (ipv6_probe_monitoring_) + new IPv6ProbeJob(probe_weak_ptr_factory_.GetWeakPtr(), net_log_); +#if defined(OS_POSIX) && !defined(OS_MACOSX) + new LoopbackProbeJob(probe_weak_ptr_factory_.GetWeakPtr()); +#endif + AbortAllInProgressJobs(); + // |this| may be deleted inside AbortAllInProgressJobs(). +} + +void HostResolverImpl::OnDNSChanged() { + DnsConfig dns_config; + NetworkChangeNotifier::GetDnsConfig(&dns_config); + if (net_log_) { + net_log_->AddGlobalEntry( + NetLog::TYPE_DNS_CONFIG_CHANGED, + base::Bind(&NetLogDnsConfigCallback, &dns_config)); + } + + // TODO(szym): Remove once http://crbug.com/137914 is resolved. + received_dns_config_ = dns_config.IsValid(); + + num_dns_failures_ = 0; + + // We want a new DnsSession in place, before we Abort running Jobs, so that + // the newly started jobs use the new config. + if (dns_client_.get()) { + dns_client_->SetConfig(dns_config); + if (dns_config.IsValid()) + UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); + } + + // If the DNS server has changed, existing cached info could be wrong so we + // have to drop our internal cache :( Note that OS level DNS caches, such + // as NSCD's cache should be dropped automatically by the OS when + // resolv.conf changes so we don't need to do anything to clear that cache. + if (cache_.get()) + cache_->clear(); + + // Life check to bail once |this| is deleted. + base::WeakPtr self = weak_ptr_factory_.GetWeakPtr(); + + // Existing jobs will have been sent to the original server so they need to + // be aborted. + AbortAllInProgressJobs(); + + // |this| may be deleted inside AbortAllInProgressJobs(). + if (self) + TryServingAllJobsFromHosts(); +} + +bool HostResolverImpl::HaveDnsConfig() const { + // Use DnsClient only if it's fully configured and there is no override by + // ScopedDefaultHostResolverProc. + // The alternative is to use NetworkChangeNotifier to override DnsConfig, + // but that would introduce construction order requirements for NCN and SDHRP. + return (dns_client_.get() != NULL) && + (dns_client_->GetConfig() != NULL) && + !(proc_params_.resolver_proc == NULL && + HostResolverProc::GetDefault() != NULL); +} + +void HostResolverImpl::OnDnsTaskResolve(int net_error) { + DCHECK(dns_client_); + if (net_error == OK) { + num_dns_failures_ = 0; + return; + } + ++num_dns_failures_; + if (num_dns_failures_ < kMaximumDnsFailures) + return; + // Disable DnsClient until the next DNS change. + for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) + it->second->AbortDnsTask(); + dns_client_->SetConfig(DnsConfig()); + UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", false); + UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.DnsClientDisabledReason", + std::abs(net_error), + GetAllErrorCodesForUma()); +} + +void HostResolverImpl::SetDnsClient(scoped_ptr dns_client) { + if (HaveDnsConfig()) { + for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) + it->second->AbortDnsTask(); + } + dns_client_ = dns_client.Pass(); + if (!dns_client_ || dns_client_->GetConfig() || + num_dns_failures_ >= kMaximumDnsFailures) { + return; + } + DnsConfig dns_config; + NetworkChangeNotifier::GetDnsConfig(&dns_config); + dns_client_->SetConfig(dns_config); + num_dns_failures_ = 0; + if (dns_config.IsValid()) + UMA_HISTOGRAM_BOOLEAN("AsyncDNS.DnsClientEnabled", true); +} + +} // namespace net diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h new file mode 100644 index 0000000..2519d13 --- /dev/null +++ b/net/dns/host_resolver_impl.h @@ -0,0 +1,287 @@ +// Copyright (c) 2012 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_DNS_HOST_RESOLVER_IMPL_H_ +#define NET_DNS_HOST_RESOLVER_IMPL_H_ + +#include + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/non_thread_safe.h" +#include "base/time.h" +#include "net/base/capturing_net_log.h" +#include "net/base/host_cache.h" +#include "net/base/net_export.h" +#include "net/base/network_change_notifier.h" +#include "net/base/prioritized_dispatcher.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_proc.h" + +namespace net { + +class BoundNetLog; +class DnsClient; +class NetLog; + +// For each hostname that is requested, HostResolver creates a +// HostResolverImpl::Job. When this job gets dispatched it creates a ProcTask +// which runs the given HostResolverProc on a WorkerPool thread. If requests for +// that same host are made during the job's lifetime, 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, fam1) (for host2, fam2) (for hostx, famx) +// / | | / | | / | | +// Request ... Request Request ... Request Request ... Request +// (port1) (port2) (port3) (port4) (port5) (portX) +// +// When a HostResolverImpl::Job finishes, 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! +// +// The HostResolverImpl enforces limits on the maximum number of concurrent +// threads using PrioritizedDispatcher::Limits. +// +// Jobs are ordered in the queue based on their priority and order of arrival. +class NET_EXPORT HostResolverImpl + : public HostResolver, + NON_EXPORTED_BASE(public base::NonThreadSafe), + public NetworkChangeNotifier::IPAddressObserver, + public NetworkChangeNotifier::DNSObserver { + public: + // Parameters for ProcTask which resolves hostnames using HostResolveProc. + // + // |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). + // + // For each attempt, we could start another attempt if host is not resolved + // within |unresponsive_delay| time. We keep attempting to resolve the host + // for |max_retry_attempts|. For every retry attempt, we grow the + // |unresponsive_delay| by the |retry_factor| amount (that is retry interval + // is multiplied by the retry factor each time). Once we have retried + // |max_retry_attempts|, we give up on additional attempts. + // + struct NET_EXPORT_PRIVATE ProcTaskParams { + // Sets up defaults. + ProcTaskParams(HostResolverProc* resolver_proc, size_t max_retry_attempts); + + ~ProcTaskParams(); + + // 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 resolver_proc; + + // Maximum number retry attempts to resolve the hostname. + // Pass HostResolver::kDefaultRetryAttempts to choose a default value. + size_t max_retry_attempts; + + // This is the limit after which we make another attempt to resolve the host + // if the worker thread has not responded yet. + base::TimeDelta unresponsive_delay; + + // Factor to grow |unresponsive_delay| when we re-re-try. + uint32 retry_factor; + }; + + // Creates a HostResolver that first uses the local cache |cache|, and then + // falls back to |proc_params.resolver_proc|. + // + // If |cache| is NULL, then no caching is used. Otherwise we take + // ownership of the |cache| pointer, and will free it during destruction. + // + // |job_limits| specifies the maximum number of jobs that the resolver will + // run at once. This upper-bounds the total number of outstanding + // DNS transactions (not counting retransmissions and retries). + // + // |net_log| must remain valid for the life of the HostResolverImpl. + HostResolverImpl(scoped_ptr cache, + const PrioritizedDispatcher::Limits& job_limits, + const ProcTaskParams& proc_params, + NetLog* net_log); + + // 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(); + + // Configures maximum number of Jobs in the queue. Exposed for testing. + // Only allowed when the queue is empty. + void SetMaxQueuedJobs(size_t value); + + // Set the DnsClient to be used for resolution. In case of failure, the + // HostResolverProc from ProcTaskParams will be queried. If the DnsClient is + // not pre-configured with a valid DnsConfig, a new config is fetched from + // NetworkChangeNotifier. + void SetDnsClient(scoped_ptr dns_client); + + // HostResolver methods: + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& source_net_log) OVERRIDE; + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& source_net_log) OVERRIDE; + virtual void CancelRequest(RequestHandle req) OVERRIDE; + virtual void SetDefaultAddressFamily(AddressFamily address_family) OVERRIDE; + virtual AddressFamily GetDefaultAddressFamily() const OVERRIDE; + virtual void ProbeIPv6Support() OVERRIDE; + virtual void SetDnsClientEnabled(bool enabled) OVERRIDE; + virtual HostCache* GetHostCache() OVERRIDE; + virtual base::Value* GetDnsConfigAsValue() const OVERRIDE; + + private: + friend class HostResolverImplTest; + class Job; + class ProcTask; + class IPv6ProbeJob; + class LoopbackProbeJob; + class DnsTask; + class Request; + typedef HostCache::Key Key; + typedef std::map JobMap; + typedef ScopedVector RequestsList; + + // Helper used by |Resolve()| and |ResolveFromCache()|. Performs IP + // literal, cache and HOSTS lookup (if enabled), returns OK if successful, + // ERR_NAME_NOT_RESOLVED if either hostname is invalid or IP literal is + // incompatible, ERR_DNS_CACHE_MISS if entry was not found in cache and HOSTS. + int ResolveHelper(const Key& key, + const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& request_net_log); + + // Tries to resolve |key| as an IP, returns true and sets |net_error| if + // succeeds, returns false otherwise. + bool ResolveAsIP(const Key& key, + const RequestInfo& info, + int* net_error, + AddressList* addresses); + + // If |key| is not found in cache returns false, otherwise returns + // true, sets |net_error| to the cached error code and fills |addresses| + // if it is a positive entry. + bool ServeFromCache(const Key& key, + const RequestInfo& info, + int* net_error, + AddressList* addresses); + + // If we have a DnsClient with a valid DnsConfig, and |key| is found in the + // HOSTS file, returns true and fills |addresses|. Otherwise returns false. + bool ServeFromHosts(const Key& key, + const RequestInfo& info, + AddressList* addresses); + + // Callback from IPv6 probe activity. + void IPv6ProbeSetDefaultAddressFamily(AddressFamily address_family); + + // Callback from HaveOnlyLoopbackAddresses probe. + void SetHaveOnlyLoopbackAddresses(bool result); + + // Returns the (hostname, address_family) key to use for |info|, choosing an + // "effective" address family by inheriting the resolver's default address + // family when the request leaves it unspecified. + Key GetEffectiveKeyForRequest(const RequestInfo& info) const; + + // Records the result in cache if cache is present. + void CacheResult(const Key& key, + const HostCache::Entry& entry, + base::TimeDelta ttl); + + // Removes |job| from |jobs_|, only if it exists. + void RemoveJob(Job* job); + + // Aborts all in progress jobs with ERR_NETWORK_CHANGED and notifies their + // requests. Might start new jobs. + void AbortAllInProgressJobs(); + + // Attempts to serve each Job in |jobs_| from the HOSTS file if we have + // a DnsClient with a valid DnsConfig. + void TryServingAllJobsFromHosts(); + + // NetworkChangeNotifier::IPAddressObserver: + virtual void OnIPAddressChanged() OVERRIDE; + + // NetworkChangeNotifier::DNSObserver: + virtual void OnDNSChanged() OVERRIDE; + + // True if have a DnsClient with a valid DnsConfig. + bool HaveDnsConfig() const; + + // Called when a host name is successfully resolved and DnsTask was run on it + // and resulted in |net_error|. + void OnDnsTaskResolve(int net_error); + + // Allows the tests to catch slots leaking out of the dispatcher. + size_t num_running_jobs_for_tests() const { + return dispatcher_.num_running_jobs(); + } + + // Cache of host resolution results. + scoped_ptr cache_; + + // Map from HostCache::Key to a Job. + JobMap jobs_; + + // Starts Jobs according to their priority and the configured limits. + PrioritizedDispatcher dispatcher_; + + // Limit on the maximum number of jobs queued in |dispatcher_|. + size_t max_queued_jobs_; + + // Parameters for ProcTask. + ProcTaskParams proc_params_; + + NetLog* net_log_; + + // Address family to use when the request doesn't specify one. + AddressFamily default_address_family_; + + base::WeakPtrFactory weak_ptr_factory_; + + base::WeakPtrFactory probe_weak_ptr_factory_; + + // If present, used by DnsTask and ServeFromHosts to resolve requests. + scoped_ptr dns_client_; + + // True if received valid config from |dns_config_service_|. Temporary, used + // to measure performance of DnsConfigService: http://crbug.com/125599 + bool received_dns_config_; + + // Number of consecutive failures of DnsTask, counted when fallback succeeds. + unsigned num_dns_failures_; + + // Indicate if probing is done after each network change event to set address + // family. When false, explicit setting of address family is used and results + // of the IPv6 probe job are ignored. + bool ipv6_probe_monitoring_; + + // True iff ProcTask has successfully resolved a hostname known to have IPv6 + // addresses using ADDRESS_FAMILY_UNSPECIFIED. Reset on IP address change. + bool resolved_known_ipv6_hostname_; + + // Any resolver flags that should be added to a request by default. + HostResolverFlags additional_resolver_flags_; + + DISALLOW_COPY_AND_ASSIGN(HostResolverImpl); +}; + +} // namespace net + +#endif // NET_DNS_HOST_RESOLVER_IMPL_H_ diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc new file mode 100644 index 0000000..4880b65 --- /dev/null +++ b/net/dns/host_resolver_impl_unittest.cc @@ -0,0 +1,1481 @@ +// Copyright (c) 2012 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/dns/host_resolver_impl.h" + +#include +#include + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_vector.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/stringprintf.h" +#include "base/synchronization/condition_variable.h" +#include "base/synchronization/lock.h" +#include "base/test/test_timeouts.h" +#include "base/time.h" +#include "net/base/address_list.h" +#include "net/base/host_cache.h" +#include "net/base/net_errors.h" +#include "net/base/net_util.h" +#include "net/dns/dns_client.h" +#include "net/dns/dns_test_util.h" +#include "net/dns/mock_host_resolver.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +const size_t kMaxJobs = 10u; +const size_t kMaxRetryAttempts = 4u; + +PrioritizedDispatcher::Limits DefaultLimits() { + PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, kMaxJobs); + return limits; +} + +HostResolverImpl::ProcTaskParams DefaultParams( + HostResolverProc* resolver_proc) { + return HostResolverImpl::ProcTaskParams(resolver_proc, kMaxRetryAttempts); +} + +// A HostResolverProc that pushes each host mapped into a list and allows +// waiting for a specific number of requests. Unlike RuleBasedHostResolverProc +// it never calls SystemHostResolverProc. By default resolves all hostnames to +// "127.0.0.1". After AddRule(), it resolves only names explicitly specified. +class MockHostResolverProc : public HostResolverProc { + public: + struct ResolveKey { + ResolveKey(const std::string& hostname, AddressFamily address_family) + : hostname(hostname), address_family(address_family) {} + bool operator<(const ResolveKey& other) const { + return address_family < other.address_family || + (address_family == other.address_family && hostname < other.hostname); + } + std::string hostname; + AddressFamily address_family; + }; + + typedef std::vector CaptureList; + + MockHostResolverProc() + : HostResolverProc(NULL), + num_requests_waiting_(0), + num_slots_available_(0), + requests_waiting_(&lock_), + slots_available_(&lock_) { + } + + // Waits until |count| calls to |Resolve| are blocked. Returns false when + // timed out. + bool WaitFor(unsigned count) { + base::AutoLock lock(lock_); + base::Time start_time = base::Time::Now(); + while (num_requests_waiting_ < count) { + requests_waiting_.TimedWait(TestTimeouts::action_timeout()); + if (base::Time::Now() > start_time + TestTimeouts::action_timeout()) + return false; + } + return true; + } + + // Signals |count| waiting calls to |Resolve|. First come first served. + void SignalMultiple(unsigned count) { + base::AutoLock lock(lock_); + num_slots_available_ += count; + slots_available_.Broadcast(); + } + + // Signals all waiting calls to |Resolve|. Beware of races. + void SignalAll() { + base::AutoLock lock(lock_); + num_slots_available_ = num_requests_waiting_; + slots_available_.Broadcast(); + } + + void AddRule(const std::string& hostname, AddressFamily family, + const AddressList& result) { + base::AutoLock lock(lock_); + rules_[ResolveKey(hostname, family)] = result; + } + + void AddRule(const std::string& hostname, AddressFamily family, + const std::string& ip_list) { + AddressList result; + int rv = ParseAddressList(ip_list, "", &result); + DCHECK_EQ(OK, rv); + AddRule(hostname, family, result); + } + + void AddRuleForAllFamilies(const std::string& hostname, + const std::string& ip_list) { + AddressList result; + int rv = ParseAddressList(ip_list, "", &result); + DCHECK_EQ(OK, rv); + AddRule(hostname, ADDRESS_FAMILY_UNSPECIFIED, result); + AddRule(hostname, ADDRESS_FAMILY_IPV4, result); + AddRule(hostname, ADDRESS_FAMILY_IPV6, result); + } + + virtual int Resolve(const std::string& hostname, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) OVERRIDE { + base::AutoLock lock(lock_); + capture_list_.push_back(ResolveKey(hostname, address_family)); + ++num_requests_waiting_; + requests_waiting_.Broadcast(); + while (!num_slots_available_) + slots_available_.Wait(); + DCHECK_GT(num_requests_waiting_, 0u); + --num_slots_available_; + --num_requests_waiting_; + if (rules_.empty()) { + int rv = ParseAddressList("127.0.0.1", "", addrlist); + DCHECK_EQ(OK, rv); + return OK; + } + ResolveKey key(hostname, address_family); + if (rules_.count(key) == 0) + return ERR_NAME_NOT_RESOLVED; + *addrlist = rules_[key]; + return OK; + } + + CaptureList GetCaptureList() const { + CaptureList copy; + { + base::AutoLock lock(lock_); + copy = capture_list_; + } + return copy; + } + + bool HasBlockedRequests() const { + base::AutoLock lock(lock_); + return num_requests_waiting_ > num_slots_available_; + } + + protected: + virtual ~MockHostResolverProc() {} + + private: + mutable base::Lock lock_; + std::map rules_; + CaptureList capture_list_; + unsigned num_requests_waiting_; + unsigned num_slots_available_; + base::ConditionVariable requests_waiting_; + base::ConditionVariable slots_available_; + + DISALLOW_COPY_AND_ASSIGN(MockHostResolverProc); +}; + +// A wrapper for requests to a HostResolver. +class Request { + public: + // Base class of handlers to be executed on completion of requests. + struct Handler { + virtual ~Handler() {} + virtual void Handle(Request* request) = 0; + }; + + Request(const HostResolver::RequestInfo& info, + size_t index, + HostResolver* resolver, + Handler* handler) + : info_(info), + index_(index), + resolver_(resolver), + handler_(handler), + quit_on_complete_(false), + result_(ERR_UNEXPECTED), + handle_(NULL) {} + + int Resolve() { + DCHECK(resolver_); + DCHECK(!handle_); + list_ = AddressList(); + result_ = resolver_->Resolve( + info_, &list_, base::Bind(&Request::OnComplete, base::Unretained(this)), + &handle_, BoundNetLog()); + if (!list_.empty()) + EXPECT_EQ(OK, result_); + return result_; + } + + int ResolveFromCache() { + DCHECK(resolver_); + DCHECK(!handle_); + return resolver_->ResolveFromCache(info_, &list_, BoundNetLog()); + } + + void Cancel() { + DCHECK(resolver_); + DCHECK(handle_); + resolver_->CancelRequest(handle_); + handle_ = NULL; + } + + const HostResolver::RequestInfo& info() const { return info_; } + size_t index() const { return index_; } + const AddressList& list() const { return list_; } + int result() const { return result_; } + bool completed() const { return result_ != ERR_IO_PENDING; } + bool pending() const { return handle_ != NULL; } + + bool HasAddress(const std::string& address, int port) const { + IPAddressNumber ip; + bool rv = ParseIPLiteralToNumber(address, &ip); + DCHECK(rv); + return std::find(list_.begin(), + list_.end(), + IPEndPoint(ip, port)) != list_.end(); + } + + // Returns the number of addresses in |list_|. + unsigned NumberOfAddresses() const { + return list_.size(); + } + + bool HasOneAddress(const std::string& address, int port) const { + return HasAddress(address, port) && (NumberOfAddresses() == 1u); + } + + // Returns ERR_UNEXPECTED if timed out. + int WaitForResult() { + if (completed()) + return result_; + base::CancelableClosure closure(MessageLoop::QuitClosure()); + MessageLoop::current()->PostDelayedTask(FROM_HERE, + closure.callback(), + TestTimeouts::action_max_timeout()); + quit_on_complete_ = true; + MessageLoop::current()->Run(); + bool did_quit = !quit_on_complete_; + quit_on_complete_ = false; + closure.Cancel(); + if (did_quit) + return result_; + else + return ERR_UNEXPECTED; + } + + private: + void OnComplete(int rv) { + EXPECT_TRUE(pending()); + EXPECT_EQ(ERR_IO_PENDING, result_); + EXPECT_NE(ERR_IO_PENDING, rv); + result_ = rv; + handle_ = NULL; + if (!list_.empty()) { + EXPECT_EQ(OK, result_); + EXPECT_EQ(info_.port(), list_.front().port()); + } + if (handler_) + handler_->Handle(this); + if (quit_on_complete_) { + MessageLoop::current()->Quit(); + quit_on_complete_ = false; + } + } + + HostResolver::RequestInfo info_; + size_t index_; + HostResolver* resolver_; + Handler* handler_; + bool quit_on_complete_; + + AddressList list_; + int result_; + HostResolver::RequestHandle handle_; + + DISALLOW_COPY_AND_ASSIGN(Request); +}; + +// Using LookupAttemptHostResolverProc simulate very long lookups, and control +// which attempt resolves the host. +class LookupAttemptHostResolverProc : public HostResolverProc { + public: + LookupAttemptHostResolverProc(HostResolverProc* previous, + int attempt_number_to_resolve, + int total_attempts) + : HostResolverProc(previous), + attempt_number_to_resolve_(attempt_number_to_resolve), + current_attempt_number_(0), + total_attempts_(total_attempts), + total_attempts_resolved_(0), + resolved_attempt_number_(0), + all_done_(&lock_) { + } + + // Test harness will wait for all attempts to finish before checking the + // results. + void WaitForAllAttemptsToFinish(const base::TimeDelta& wait_time) { + base::TimeTicks end_time = base::TimeTicks::Now() + wait_time; + { + base::AutoLock auto_lock(lock_); + while (total_attempts_resolved_ != total_attempts_ && + base::TimeTicks::Now() < end_time) { + all_done_.TimedWait(end_time - base::TimeTicks::Now()); + } + } + } + + // All attempts will wait for an attempt to resolve the host. + void WaitForAnAttemptToComplete() { + base::TimeDelta wait_time = base::TimeDelta::FromSeconds(60); + base::TimeTicks end_time = base::TimeTicks::Now() + wait_time; + { + base::AutoLock auto_lock(lock_); + while (resolved_attempt_number_ == 0 && base::TimeTicks::Now() < end_time) + all_done_.TimedWait(end_time - base::TimeTicks::Now()); + } + all_done_.Broadcast(); // Tell all waiting attempts to proceed. + } + + // Returns the number of attempts that have finished the Resolve() method. + int total_attempts_resolved() { return total_attempts_resolved_; } + + // Returns the first attempt that that has resolved the host. + int resolved_attempt_number() { return resolved_attempt_number_; } + + // HostResolverProc methods. + virtual int Resolve(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) OVERRIDE { + bool wait_for_right_attempt_to_complete = true; + { + base::AutoLock auto_lock(lock_); + ++current_attempt_number_; + if (current_attempt_number_ == attempt_number_to_resolve_) { + resolved_attempt_number_ = current_attempt_number_; + wait_for_right_attempt_to_complete = false; + } + } + + if (wait_for_right_attempt_to_complete) + // Wait for the attempt_number_to_resolve_ attempt to resolve. + WaitForAnAttemptToComplete(); + + int result = ResolveUsingPrevious(host, address_family, host_resolver_flags, + addrlist, os_error); + + { + base::AutoLock auto_lock(lock_); + ++total_attempts_resolved_; + } + + all_done_.Broadcast(); // Tell all attempts to proceed. + + // Since any negative number is considered a network error, with -1 having + // special meaning (ERR_IO_PENDING). We could return the attempt that has + // resolved the host as a negative number. For example, if attempt number 3 + // resolves the host, then this method returns -4. + if (result == OK) + return -1 - resolved_attempt_number_; + else + return result; + } + + protected: + virtual ~LookupAttemptHostResolverProc() {} + + private: + int attempt_number_to_resolve_; + int current_attempt_number_; // Incremented whenever Resolve is called. + int total_attempts_; + int total_attempts_resolved_; + int resolved_attempt_number_; + + // All attempts wait for right attempt to be resolve. + base::Lock lock_; + base::ConditionVariable all_done_; +}; + +} // namespace + +class HostResolverImplTest : public testing::Test { + public: + static const int kDefaultPort = 80; + + HostResolverImplTest() : proc_(new MockHostResolverProc()) {} + + protected: + // A Request::Handler which is a proxy to the HostResolverImplTest fixture. + struct Handler : public Request::Handler { + virtual ~Handler() {} + + // Proxy functions so that classes derived from Handler can access them. + Request* CreateRequest(const HostResolver::RequestInfo& info) { + return test->CreateRequest(info); + } + Request* CreateRequest(const std::string& hostname, int port) { + return test->CreateRequest(hostname, port); + } + Request* CreateRequest(const std::string& hostname) { + return test->CreateRequest(hostname); + } + ScopedVector& requests() { return test->requests_; } + + void DeleteResolver() { test->resolver_.reset(); } + + HostResolverImplTest* test; + }; + + void CreateResolver() { + resolver_.reset(new HostResolverImpl( + HostCache::CreateDefaultCache(), + DefaultLimits(), + DefaultParams(proc_), + NULL)); + } + + // This HostResolverImpl will only allow 1 outstanding resolve at a time and + // perform no retries. + void CreateSerialResolver() { + HostResolverImpl::ProcTaskParams params = DefaultParams(proc_); + params.max_retry_attempts = 0u; + PrioritizedDispatcher::Limits limits(NUM_PRIORITIES, 1); + resolver_.reset(new HostResolverImpl( + HostCache::CreateDefaultCache(), + limits, + params, + NULL)); + } + + // The Request will not be made until a call to |Resolve()|, and the Job will + // not start until released by |proc_->SignalXXX|. + Request* CreateRequest(const HostResolver::RequestInfo& info) { + Request* req = new Request(info, requests_.size(), resolver_.get(), + handler_.get()); + requests_.push_back(req); + return req; + } + + Request* CreateRequest(const std::string& hostname, + int port, + RequestPriority priority, + AddressFamily family) { + HostResolver::RequestInfo info(HostPortPair(hostname, port)); + info.set_priority(priority); + info.set_address_family(family); + return CreateRequest(info); + } + + Request* CreateRequest(const std::string& hostname, + int port, + RequestPriority priority) { + return CreateRequest(hostname, port, priority, ADDRESS_FAMILY_UNSPECIFIED); + } + + Request* CreateRequest(const std::string& hostname, int port) { + return CreateRequest(hostname, port, MEDIUM); + } + + Request* CreateRequest(const std::string& hostname) { + return CreateRequest(hostname, kDefaultPort); + } + + virtual void SetUp() OVERRIDE { + CreateResolver(); + } + + virtual void TearDown() OVERRIDE { + if (resolver_.get()) + EXPECT_EQ(0u, resolver_->num_running_jobs_for_tests()); + EXPECT_FALSE(proc_->HasBlockedRequests()); + } + + void set_handler(Handler* handler) { + handler_.reset(handler); + handler_->test = this; + } + + // Friendship is not inherited, so use proxies to access those. + size_t num_running_jobs() const { + DCHECK(resolver_.get()); + return resolver_->num_running_jobs_for_tests(); + } + + scoped_refptr proc_; + scoped_ptr resolver_; + ScopedVector requests_; + + scoped_ptr handler_; +}; + +TEST_F(HostResolverImplTest, AsynchronousLookup) { + proc_->AddRuleForAllFamilies("just.testing", "192.168.1.42"); + proc_->SignalMultiple(1u); + + Request* req = CreateRequest("just.testing", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); + + EXPECT_TRUE(req->HasOneAddress("192.168.1.42", 80)); + + EXPECT_EQ("just.testing", proc_->GetCaptureList()[0].hostname); +} + +TEST_F(HostResolverImplTest, FailedAsynchronousLookup) { + proc_->AddRuleForAllFamilies("", "0.0.0.0"); // Default to failures. + proc_->SignalMultiple(1u); + + Request* req = CreateRequest("just.testing", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->WaitForResult()); + + EXPECT_EQ("just.testing", proc_->GetCaptureList()[0].hostname); + + // Also test that the error is not cached. + EXPECT_EQ(ERR_DNS_CACHE_MISS, req->ResolveFromCache()); +} + +TEST_F(HostResolverImplTest, AbortedAsynchronousLookup) { + Request* req0 = CreateRequest("just.testing", 80); + EXPECT_EQ(ERR_IO_PENDING, req0->Resolve()); + + EXPECT_TRUE(proc_->WaitFor(1u)); + + // Resolver is destroyed while job is running on WorkerPool. + resolver_.reset(); + + proc_->SignalAll(); + + // To ensure there was no spurious callback, complete with a new resolver. + CreateResolver(); + Request* req1 = CreateRequest("just.testing", 80); + EXPECT_EQ(ERR_IO_PENDING, req1->Resolve()); + + proc_->SignalMultiple(2u); + + EXPECT_EQ(OK, req1->WaitForResult()); + + // This request was canceled. + EXPECT_FALSE(req0->completed()); +} + +TEST_F(HostResolverImplTest, NumericIPv4Address) { + // Stevens says dotted quads with AI_UNSPEC resolve to a single sockaddr_in. + Request* req = CreateRequest("127.1.2.3", 5555); + EXPECT_EQ(OK, req->Resolve()); + + EXPECT_TRUE(req->HasOneAddress("127.1.2.3", 5555)); +} + +TEST_F(HostResolverImplTest, NumericIPv6Address) { + // Resolve a plain IPv6 address. Don't worry about [brackets], because + // the caller should have removed them. + Request* req = CreateRequest("2001:db8::1", 5555); + EXPECT_EQ(OK, req->Resolve()); + + EXPECT_TRUE(req->HasOneAddress("2001:db8::1", 5555)); +} + +TEST_F(HostResolverImplTest, EmptyHost) { + Request* req = CreateRequest("", 5555); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->Resolve()); +} + +TEST_F(HostResolverImplTest, LongHost) { + Request* req = CreateRequest(std::string(4097, 'a'), 5555); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->Resolve()); +} + +TEST_F(HostResolverImplTest, DeDupeRequests) { + // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is + // blocked, these should all pile up until we signal it. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 81)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 82)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); + + proc_->SignalMultiple(2u); // One for "a", one for "b". + + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + } +} + +TEST_F(HostResolverImplTest, CancelMultipleRequests) { + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 81)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 82)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); + + // Cancel everything except request for ("a", 82). + requests_[0]->Cancel(); + requests_[1]->Cancel(); + requests_[2]->Cancel(); + requests_[4]->Cancel(); + + proc_->SignalMultiple(2u); // One for "a", one for "b". + + EXPECT_EQ(OK, requests_[3]->WaitForResult()); +} + +TEST_F(HostResolverImplTest, CanceledRequestsReleaseJobSlots) { + // Fill up the dispatcher and queue. + for (unsigned i = 0; i < kMaxJobs + 1; ++i) { + std::string hostname = "a_"; + hostname[1] = 'a' + i; + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 81)->Resolve()); + } + + EXPECT_TRUE(proc_->WaitFor(kMaxJobs)); + + // Cancel all but last two. + for (unsigned i = 0; i < requests_.size() - 2; ++i) { + requests_[i]->Cancel(); + } + + EXPECT_TRUE(proc_->WaitFor(kMaxJobs + 1)); + + proc_->SignalAll(); + + size_t num_requests = requests_.size(); + EXPECT_EQ(OK, requests_[num_requests - 1]->WaitForResult()); + EXPECT_EQ(OK, requests_[num_requests - 2]->result()); +} + +TEST_F(HostResolverImplTest, CancelWithinCallback) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + // Port 80 is the first request that the callback will be invoked for. + // While we are executing within that callback, cancel the other requests + // in the job and start another request. + if (req->index() == 0) { + // Once "a:80" completes, it will cancel "a:81" and "a:82". + requests()[1]->Cancel(); + requests()[2]->Cancel(); + } + } + }; + set_handler(new MyHandler()); + + for (size_t i = 0; i < 4; ++i) { + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; + } + + proc_->SignalMultiple(2u); // One for "a". One for "finalrequest". + + EXPECT_EQ(OK, requests_[0]->WaitForResult()); + + Request* final_request = CreateRequest("finalrequest", 70); + EXPECT_EQ(ERR_IO_PENDING, final_request->Resolve()); + EXPECT_EQ(OK, final_request->WaitForResult()); + EXPECT_TRUE(requests_[3]->completed()); +} + +TEST_F(HostResolverImplTest, DeleteWithinCallback) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + EXPECT_EQ("a", req->info().hostname()); + EXPECT_EQ(80, req->info().port()); + + DeleteResolver(); + + // Quit after returning from OnCompleted (to give it a chance at + // incorrectly running the cancelled tasks). + MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); + } + }; + set_handler(new MyHandler()); + + for (size_t i = 0; i < 4; ++i) { + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; + } + + proc_->SignalMultiple(1u); // One for "a". + + // |MyHandler| will send quit message once all the requests have finished. + MessageLoop::current()->Run(); +} + +TEST_F(HostResolverImplTest, DeleteWithinAbortedCallback) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + EXPECT_EQ("a", req->info().hostname()); + EXPECT_EQ(80, req->info().port()); + + DeleteResolver(); + + // Quit after returning from OnCompleted (to give it a chance at + // incorrectly running the cancelled tasks). + MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); + } + }; + set_handler(new MyHandler()); + + // This test assumes that the Jobs will be Aborted in order ["a", "b"] + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); + // HostResolverImpl will be deleted before later Requests can complete. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 81)->Resolve()); + // Job for 'b' will be aborted before it can complete. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 82)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b", 83)->Resolve()); + + EXPECT_TRUE(proc_->WaitFor(1u)); + + // Triggering an IP address change. + NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + + // |MyHandler| will send quit message once all the requests have finished. + MessageLoop::current()->Run(); + + EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->result()); + EXPECT_EQ(ERR_IO_PENDING, requests_[1]->result()); + EXPECT_EQ(ERR_IO_PENDING, requests_[2]->result()); + EXPECT_EQ(ERR_IO_PENDING, requests_[3]->result()); + // Clean up. + proc_->SignalMultiple(requests_.size()); +} + +TEST_F(HostResolverImplTest, StartWithinCallback) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + if (req->index() == 0) { + // On completing the first request, start another request for "a". + // Since caching is disabled, this will result in another async request. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 70)->Resolve()); + } + } + }; + set_handler(new MyHandler()); + + // Turn off caching for this host resolver. + resolver_.reset(new HostResolverImpl( + scoped_ptr(), + DefaultLimits(), + DefaultParams(proc_), + NULL)); + + for (size_t i = 0; i < 4; ++i) { + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80 + i)->Resolve()) << i; + } + + proc_->SignalMultiple(2u); // One for "a". One for the second "a". + + EXPECT_EQ(OK, requests_[0]->WaitForResult()); + ASSERT_EQ(5u, requests_.size()); + EXPECT_EQ(OK, requests_.back()->WaitForResult()); + + EXPECT_EQ(2u, proc_->GetCaptureList().size()); +} + +TEST_F(HostResolverImplTest, BypassCache) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + if (req->index() == 0) { + // On completing the first request, start another request for "a". + // Since caching is enabled, this should complete synchronously. + std::string hostname = req->info().hostname(); + EXPECT_EQ(OK, CreateRequest(hostname, 70)->Resolve()); + EXPECT_EQ(OK, CreateRequest(hostname, 75)->ResolveFromCache()); + + // Ok good. Now make sure that if we ask to bypass the cache, it can no + // longer service the request synchronously. + HostResolver::RequestInfo info(HostPortPair(hostname, 71)); + info.set_allow_cached_response(false); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(info)->Resolve()); + } else if (71 == req->info().port()) { + // Test is done. + MessageLoop::current()->Quit(); + } else { + FAIL() << "Unexpected request"; + } + } + }; + set_handler(new MyHandler()); + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a", 80)->Resolve()); + proc_->SignalMultiple(3u); // Only need two, but be generous. + + // |verifier| will send quit message once all the requests have finished. + MessageLoop::current()->Run(); + EXPECT_EQ(2u, proc_->GetCaptureList().size()); +} + +// Test that IP address changes flush the cache. +TEST_F(HostResolverImplTest, FlushCacheOnIPAddressChange) { + proc_->SignalMultiple(2u); // One before the flush, one after. + + Request* req = CreateRequest("host1", 70); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); + + req = CreateRequest("host1", 75); + EXPECT_EQ(OK, req->Resolve()); // Should complete synchronously. + + // Flush cache by triggering an IP address change. + NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + MessageLoop::current()->RunUntilIdle(); // Notification happens async. + + // Resolve "host1" again -- this time it won't be served from cache, so it + // will complete asynchronously. + req = CreateRequest("host1", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); +} + +// Test that IP address changes send ERR_NETWORK_CHANGED to pending requests. +TEST_F(HostResolverImplTest, AbortOnIPAddressChanged) { + Request* req = CreateRequest("host1", 70); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + + EXPECT_TRUE(proc_->WaitFor(1u)); + // Triggering an IP address change. + NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + MessageLoop::current()->RunUntilIdle(); // Notification happens async. + proc_->SignalAll(); + + EXPECT_EQ(ERR_NETWORK_CHANGED, req->WaitForResult()); + EXPECT_EQ(0u, resolver_->GetHostCache()->size()); +} + +// Obey pool constraints after IP address has changed. +TEST_F(HostResolverImplTest, ObeyPoolConstraintsAfterIPAddressChange) { + // Runs at most one job at a time. + CreateSerialResolver(); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("a")->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("b")->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("c")->Resolve()); + + EXPECT_TRUE(proc_->WaitFor(1u)); + // Triggering an IP address change. + NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + MessageLoop::current()->RunUntilIdle(); // Notification happens async. + proc_->SignalMultiple(3u); // Let the false-start go so that we can catch it. + + EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->WaitForResult()); + + EXPECT_EQ(1u, num_running_jobs()); + + EXPECT_FALSE(requests_[1]->completed()); + EXPECT_FALSE(requests_[2]->completed()); + + EXPECT_EQ(OK, requests_[2]->WaitForResult()); + EXPECT_EQ(OK, requests_[1]->result()); +} + +// Tests that a new Request made from the callback of a previously aborted one +// will not be aborted. +TEST_F(HostResolverImplTest, AbortOnlyExistingRequestsOnIPAddressChange) { + struct MyHandler : public Handler { + virtual void Handle(Request* req) OVERRIDE { + // Start new request for a different hostname to ensure that the order + // of jobs in HostResolverImpl is not stable. + std::string hostname; + if (req->index() == 0) + hostname = "zzz"; + else if (req->index() == 1) + hostname = "aaa"; + else if (req->index() == 2) + hostname = "eee"; + else + return; // A request started from within MyHandler. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname)->Resolve()) << hostname; + } + }; + set_handler(new MyHandler()); + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("bbb")->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("eee")->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ccc")->Resolve()); + + // Wait until all are blocked; + EXPECT_TRUE(proc_->WaitFor(3u)); + // Trigger an IP address change. + NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); + // This should abort all running jobs. + MessageLoop::current()->RunUntilIdle(); + EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[0]->result()); + EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[1]->result()); + EXPECT_EQ(ERR_NETWORK_CHANGED, requests_[2]->result()); + ASSERT_EQ(6u, requests_.size()); + // Unblock all calls to proc. + proc_->SignalMultiple(requests_.size()); + // Run until the re-started requests finish. + EXPECT_EQ(OK, requests_[3]->WaitForResult()); + EXPECT_EQ(OK, requests_[4]->WaitForResult()); + EXPECT_EQ(OK, requests_[5]->WaitForResult()); + // Verify that results of aborted Jobs were not cached. + EXPECT_EQ(6u, proc_->GetCaptureList().size()); + EXPECT_EQ(3u, resolver_->GetHostCache()->size()); +} + +// Tests that when the maximum threads is set to 1, requests are dequeued +// in order of priority. +TEST_F(HostResolverImplTest, HigherPriorityRequestsStartedFirst) { + CreateSerialResolver(); + + // Note that at this point the MockHostResolverProc is blocked, so any + // requests we make will not complete. + CreateRequest("req0", 80, LOW); + CreateRequest("req1", 80, MEDIUM); + CreateRequest("req2", 80, MEDIUM); + CreateRequest("req3", 80, LOW); + CreateRequest("req4", 80, HIGHEST); + CreateRequest("req5", 80, LOW); + CreateRequest("req6", 80, LOW); + CreateRequest("req5", 80, HIGHEST); + + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; + } + + // Unblock the resolver thread so the requests can run. + proc_->SignalMultiple(requests_.size()); // More than needed. + + // Wait for all the requests to complete succesfully. + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + } + + // Since we have restricted to a single concurrent thread in the jobpool, + // the requests should complete in order of priority (with the exception + // of the first request, which gets started right away, since there is + // nothing outstanding). + MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); + ASSERT_EQ(7u, capture_list.size()); + + EXPECT_EQ("req0", capture_list[0].hostname); + EXPECT_EQ("req4", capture_list[1].hostname); + EXPECT_EQ("req5", capture_list[2].hostname); + EXPECT_EQ("req1", capture_list[3].hostname); + EXPECT_EQ("req2", capture_list[4].hostname); + EXPECT_EQ("req3", capture_list[5].hostname); + EXPECT_EQ("req6", capture_list[6].hostname); +} + +// Try cancelling a job which has not started yet. +TEST_F(HostResolverImplTest, CancelPendingRequest) { + CreateSerialResolver(); + + CreateRequest("req0", 80, LOWEST); + CreateRequest("req1", 80, HIGHEST); // Will cancel. + CreateRequest("req2", 80, MEDIUM); + CreateRequest("req3", 80, LOW); + CreateRequest("req4", 80, HIGHEST); // Will cancel. + CreateRequest("req5", 80, LOWEST); // Will cancel. + CreateRequest("req6", 80, MEDIUM); + + // Start all of the requests. + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; + } + + // Cancel some requests + requests_[1]->Cancel(); + requests_[4]->Cancel(); + requests_[5]->Cancel(); + + // Unblock the resolver thread so the requests can run. + proc_->SignalMultiple(requests_.size()); // More than needed. + + // Wait for all the requests to complete succesfully. + for (size_t i = 0; i < requests_.size(); ++i) { + if (!requests_[i]->pending()) + continue; // Don't wait for the requests we cancelled. + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + } + + // Verify that they called out the the resolver proc (which runs on the + // resolver thread) in the expected order. + MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); + ASSERT_EQ(4u, capture_list.size()); + + EXPECT_EQ("req0", capture_list[0].hostname); + EXPECT_EQ("req2", capture_list[1].hostname); + EXPECT_EQ("req6", capture_list[2].hostname); + EXPECT_EQ("req3", capture_list[3].hostname); +} + +// Test that when too many requests are enqueued, old ones start to be aborted. +TEST_F(HostResolverImplTest, QueueOverflow) { + CreateSerialResolver(); + + // Allow only 3 queued jobs. + const size_t kMaxPendingJobs = 3u; + resolver_->SetMaxQueuedJobs(kMaxPendingJobs); + + // Note that at this point the MockHostResolverProc is blocked, so any + // requests we make will not complete. + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req0", 80, LOWEST)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req1", 80, HIGHEST)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req2", 80, MEDIUM)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req3", 80, MEDIUM)->Resolve()); + + // At this point, there are 3 enqueued jobs. + // Insertion of subsequent requests will cause evictions + // based on priority. + + EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, + CreateRequest("req4", 80, LOW)->Resolve()); // Evicts itself! + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req5", 80, MEDIUM)->Resolve()); + EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[2]->result()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req6", 80, HIGHEST)->Resolve()); + EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[3]->result()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("req7", 80, MEDIUM)->Resolve()); + EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, requests_[5]->result()); + + // Unblock the resolver thread so the requests can run. + proc_->SignalMultiple(4u); + + // The rest should succeed. + EXPECT_EQ(OK, requests_[7]->WaitForResult()); + EXPECT_EQ(OK, requests_[0]->result()); + EXPECT_EQ(OK, requests_[1]->result()); + EXPECT_EQ(OK, requests_[6]->result()); + + // Verify that they called out the the resolver proc (which runs on the + // resolver thread) in the expected order. + MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); + ASSERT_EQ(4u, capture_list.size()); + + EXPECT_EQ("req0", capture_list[0].hostname); + EXPECT_EQ("req1", capture_list[1].hostname); + EXPECT_EQ("req6", capture_list[2].hostname); + EXPECT_EQ("req7", capture_list[3].hostname); + + // Verify that the evicted (incomplete) requests were not cached. + EXPECT_EQ(4u, resolver_->GetHostCache()->size()); + + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_TRUE(requests_[i]->completed()) << i; + } +} + +// Tests that after changing the default AddressFamily to IPV4, requests +// with UNSPECIFIED address family map to IPV4. +TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv4) { + CreateSerialResolver(); // To guarantee order of resolutions. + + proc_->AddRule("h1", ADDRESS_FAMILY_IPV4, "1.0.0.1"); + proc_->AddRule("h1", ADDRESS_FAMILY_IPV6, "::2"); + + resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); + + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_UNSPECIFIED); + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV4); + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV6); + + // Start all of the requests. + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; + } + + proc_->SignalMultiple(requests_.size()); + + // Wait for all the requests to complete. + for (size_t i = 0u; i < requests_.size(); ++i) { + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + } + + // Since the requests all had the same priority and we limited the thread + // count to 1, they should have completed in the same order as they were + // requested. Moreover, request0 and request1 will have been serviced by + // the same job. + + MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); + ASSERT_EQ(2u, capture_list.size()); + + EXPECT_EQ("h1", capture_list[0].hostname); + EXPECT_EQ(ADDRESS_FAMILY_IPV4, capture_list[0].address_family); + + EXPECT_EQ("h1", capture_list[1].hostname); + EXPECT_EQ(ADDRESS_FAMILY_IPV6, capture_list[1].address_family); + + // Now check that the correct resolved IP addresses were returned. + EXPECT_TRUE(requests_[0]->HasOneAddress("1.0.0.1", 80)); + EXPECT_TRUE(requests_[1]->HasOneAddress("1.0.0.1", 80)); + EXPECT_TRUE(requests_[2]->HasOneAddress("::2", 80)); +} + +// This is the exact same test as SetDefaultAddressFamily_IPv4, except the +// default family is set to IPv6 and the family of requests is flipped where +// specified. +TEST_F(HostResolverImplTest, SetDefaultAddressFamily_IPv6) { + CreateSerialResolver(); // To guarantee order of resolutions. + + // Don't use IPv6 replacements here since some systems don't support it. + proc_->AddRule("h1", ADDRESS_FAMILY_IPV4, "1.0.0.1"); + proc_->AddRule("h1", ADDRESS_FAMILY_IPV6, "::2"); + + resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV6); + + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_UNSPECIFIED); + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV6); + CreateRequest("h1", 80, MEDIUM, ADDRESS_FAMILY_IPV4); + + // Start all of the requests. + for (size_t i = 0; i < requests_.size(); ++i) { + EXPECT_EQ(ERR_IO_PENDING, requests_[i]->Resolve()) << i; + } + + proc_->SignalMultiple(requests_.size()); + + // Wait for all the requests to complete. + for (size_t i = 0u; i < requests_.size(); ++i) { + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + } + + // Since the requests all had the same priority and we limited the thread + // count to 1, they should have completed in the same order as they were + // requested. Moreover, request0 and request1 will have been serviced by + // the same job. + + MockHostResolverProc::CaptureList capture_list = proc_->GetCaptureList(); + ASSERT_EQ(2u, capture_list.size()); + + EXPECT_EQ("h1", capture_list[0].hostname); + EXPECT_EQ(ADDRESS_FAMILY_IPV6, capture_list[0].address_family); + + EXPECT_EQ("h1", capture_list[1].hostname); + EXPECT_EQ(ADDRESS_FAMILY_IPV4, capture_list[1].address_family); + + // Now check that the correct resolved IP addresses were returned. + EXPECT_TRUE(requests_[0]->HasOneAddress("::2", 80)); + EXPECT_TRUE(requests_[1]->HasOneAddress("::2", 80)); + EXPECT_TRUE(requests_[2]->HasOneAddress("1.0.0.1", 80)); +} + +TEST_F(HostResolverImplTest, ResolveFromCache) { + proc_->AddRuleForAllFamilies("just.testing", "192.168.1.42"); + proc_->SignalMultiple(1u); // Need only one. + + HostResolver::RequestInfo info(HostPortPair("just.testing", 80)); + + // First hit will miss the cache. + EXPECT_EQ(ERR_DNS_CACHE_MISS, CreateRequest(info)->ResolveFromCache()); + + // This time, we fetch normally. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(info)->Resolve()); + EXPECT_EQ(OK, requests_[1]->WaitForResult()); + + // Now we should be able to fetch from the cache. + EXPECT_EQ(OK, CreateRequest(info)->ResolveFromCache()); + EXPECT_TRUE(requests_[2]->HasOneAddress("192.168.1.42", 80)); +} + +// Test the retry attempts simulating host resolver proc that takes too long. +TEST_F(HostResolverImplTest, MultipleAttempts) { + // Total number of attempts would be 3 and we want the 3rd attempt to resolve + // the host. First and second attempt will be forced to sleep until they get + // word that a resolution has completed. The 3rd resolution attempt will try + // to get done ASAP, and won't sleep.. + int kAttemptNumberToResolve = 3; + int kTotalAttempts = 3; + + scoped_refptr resolver_proc( + new LookupAttemptHostResolverProc( + NULL, kAttemptNumberToResolve, kTotalAttempts)); + + HostResolverImpl::ProcTaskParams params = DefaultParams(resolver_proc.get()); + + // Specify smaller interval for unresponsive_delay_ for HostResolverImpl so + // that unit test runs faster. For example, this test finishes in 1.5 secs + // (500ms * 3). + params.unresponsive_delay = base::TimeDelta::FromMilliseconds(500); + + resolver_.reset( + new HostResolverImpl(HostCache::CreateDefaultCache(), + DefaultLimits(), + params, + NULL)); + + // Resolve "host1". + HostResolver::RequestInfo info(HostPortPair("host1", 70)); + Request* req = CreateRequest(info); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + + // Resolve returns -4 to indicate that 3rd attempt has resolved the host. + EXPECT_EQ(-4, req->WaitForResult()); + + resolver_proc->WaitForAllAttemptsToFinish( + base::TimeDelta::FromMilliseconds(60000)); + MessageLoop::current()->RunUntilIdle(); + + EXPECT_EQ(resolver_proc->total_attempts_resolved(), kTotalAttempts); + EXPECT_EQ(resolver_proc->resolved_attempt_number(), kAttemptNumberToResolve); +} + +DnsConfig CreateValidDnsConfig() { + IPAddressNumber dns_ip; + bool rv = ParseIPLiteralToNumber("192.168.1.0", &dns_ip); + EXPECT_TRUE(rv); + + DnsConfig config; + config.nameservers.push_back(IPEndPoint(dns_ip, dns_protocol::kDefaultPort)); + EXPECT_TRUE(config.IsValid()); + return config; +} + +// Specialized fixture for tests of DnsTask. +class HostResolverImplDnsTest : public HostResolverImplTest { + protected: + virtual void SetUp() OVERRIDE { + AddDnsRule("er", dns_protocol::kTypeA, MockDnsClientRule::FAIL_SYNC); + AddDnsRule("er", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_SYNC); + AddDnsRule("nx", dns_protocol::kTypeA, MockDnsClientRule::FAIL_ASYNC); + AddDnsRule("nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_ASYNC); + AddDnsRule("ok", dns_protocol::kTypeA, MockDnsClientRule::OK); + AddDnsRule("ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); + AddDnsRule("4ok", dns_protocol::kTypeA, MockDnsClientRule::OK); + AddDnsRule("4ok", dns_protocol::kTypeAAAA, MockDnsClientRule::EMPTY); + AddDnsRule("6ok", dns_protocol::kTypeA, MockDnsClientRule::EMPTY); + AddDnsRule("6ok", dns_protocol::kTypeAAAA, MockDnsClientRule::OK); + AddDnsRule("4nx", dns_protocol::kTypeA, MockDnsClientRule::OK); + AddDnsRule("4nx", dns_protocol::kTypeAAAA, MockDnsClientRule::FAIL_ASYNC); + CreateResolver(); + } + + void CreateResolver() { + resolver_.reset(new HostResolverImpl( + HostCache::CreateDefaultCache(), + DefaultLimits(), + DefaultParams(proc_), + NULL)); + resolver_->SetDnsClient(CreateMockDnsClient(DnsConfig(), dns_rules_)); + } + + // Adds a rule to |dns_rules_|. Must be followed by |CreateResolver| to apply. + void AddDnsRule(const std::string& prefix, + uint16 qtype, + MockDnsClientRule::Result result) { + dns_rules_.push_back(MockDnsClientRule(prefix, qtype, result)); + } + + void ChangeDnsConfig(const DnsConfig& config) { + NetworkChangeNotifier::SetDnsConfig(config); + // Notification is delivered asynchronously. + MessageLoop::current()->RunUntilIdle(); + } + + MockDnsClientRuleList dns_rules_; +}; + +// TODO(szym): Test AbortAllInProgressJobs due to DnsConfig change. + +// TODO(cbentzel): Test a mix of requests with different HostResolverFlags. + +// Test successful and fallback resolutions in HostResolverImpl::DnsTask. +TEST_F(HostResolverImplDnsTest, DnsTask) { + resolver_->SetDefaultAddressFamily(ADDRESS_FAMILY_IPV4); + + proc_->AddRuleForAllFamilies("er_succeed", "192.168.1.101"); + proc_->AddRuleForAllFamilies("nx_succeed", "192.168.1.102"); + // All other hostnames will fail in proc_. + + // Initially there is no config, so client should not be invoked. + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok_fail", 80)->Resolve()); + proc_->SignalMultiple(requests_.size()); + + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[0]->WaitForResult()); + + ChangeDnsConfig(CreateValidDnsConfig()); + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok_fail", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("er_fail", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("nx_fail", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("er_succeed", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("nx_succeed", 80)->Resolve()); + + proc_->SignalMultiple(requests_.size()); + + for (size_t i = 1; i < requests_.size(); ++i) + EXPECT_NE(ERR_UNEXPECTED, requests_[i]->WaitForResult()) << i; + + EXPECT_EQ(OK, requests_[1]->result()); + // Resolved by MockDnsClient. + EXPECT_TRUE(requests_[1]->HasOneAddress("127.0.0.1", 80)); + // Fallback to ProcTask. + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[2]->result()); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[3]->result()); + EXPECT_EQ(OK, requests_[4]->result()); + EXPECT_TRUE(requests_[4]->HasOneAddress("192.168.1.101", 80)); + EXPECT_EQ(OK, requests_[5]->result()); + EXPECT_TRUE(requests_[5]->HasOneAddress("192.168.1.102", 80)); +} + +TEST_F(HostResolverImplDnsTest, DnsTaskUnspec) { + ChangeDnsConfig(CreateValidDnsConfig()); + + proc_->AddRuleForAllFamilies("4nx", "192.168.1.101"); + // All other hostnames will fail in proc_. + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4ok", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("6ok", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("4nx", 80)->Resolve()); + + proc_->SignalMultiple(requests_.size()); + + for (size_t i = 0; i < requests_.size(); ++i) + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + + EXPECT_EQ(2u, requests_[0]->NumberOfAddresses()); + EXPECT_TRUE(requests_[0]->HasAddress("127.0.0.1", 80)); + EXPECT_TRUE(requests_[0]->HasAddress("::1", 80)); + EXPECT_EQ(1u, requests_[1]->NumberOfAddresses()); + EXPECT_TRUE(requests_[1]->HasAddress("127.0.0.1", 80)); + EXPECT_EQ(1u, requests_[2]->NumberOfAddresses()); + EXPECT_TRUE(requests_[2]->HasAddress("::1", 80)); + EXPECT_EQ(1u, requests_[3]->NumberOfAddresses()); + EXPECT_TRUE(requests_[3]->HasAddress("192.168.1.101", 80)); +} + +TEST_F(HostResolverImplDnsTest, ServeFromHosts) { + // Initially, use empty HOSTS file. + DnsConfig config = CreateValidDnsConfig(); + ChangeDnsConfig(config); + + proc_->AddRuleForAllFamilies("", ""); // Default to failures. + proc_->SignalMultiple(1u); // For the first request which misses. + + Request* req0 = CreateRequest("er_ipv4", 80); + EXPECT_EQ(ERR_IO_PENDING, req0->Resolve()); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req0->WaitForResult()); + + IPAddressNumber local_ipv4, local_ipv6; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &local_ipv4)); + ASSERT_TRUE(ParseIPLiteralToNumber("::1", &local_ipv6)); + + DnsHosts hosts; + hosts[DnsHostsKey("er_ipv4", ADDRESS_FAMILY_IPV4)] = local_ipv4; + hosts[DnsHostsKey("er_ipv6", ADDRESS_FAMILY_IPV6)] = local_ipv6; + hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV4)] = local_ipv4; + hosts[DnsHostsKey("er_both", ADDRESS_FAMILY_IPV6)] = local_ipv6; + + // Update HOSTS file. + config.hosts = hosts; + ChangeDnsConfig(config); + + Request* req1 = CreateRequest("er_ipv4", 80); + EXPECT_EQ(OK, req1->Resolve()); + EXPECT_TRUE(req1->HasOneAddress("127.0.0.1", 80)); + + Request* req2 = CreateRequest("er_ipv6", 80); + EXPECT_EQ(OK, req2->Resolve()); + EXPECT_TRUE(req2->HasOneAddress("::1", 80)); + + Request* req3 = CreateRequest("er_both", 80); + EXPECT_EQ(OK, req3->Resolve()); + EXPECT_TRUE(req3->HasOneAddress("127.0.0.1", 80) || + req3->HasOneAddress("::1", 80)); + + // Requests with specified AddressFamily. + Request* req4 = CreateRequest("er_ipv4", 80, MEDIUM, ADDRESS_FAMILY_IPV4); + EXPECT_EQ(OK, req4->Resolve()); + EXPECT_TRUE(req4->HasOneAddress("127.0.0.1", 80)); + + Request* req5 = CreateRequest("er_ipv6", 80, MEDIUM, ADDRESS_FAMILY_IPV6); + EXPECT_EQ(OK, req5->Resolve()); + EXPECT_TRUE(req5->HasOneAddress("::1", 80)); + + // Request with upper case. + Request* req6 = CreateRequest("er_IPV4", 80); + EXPECT_EQ(OK, req6->Resolve()); + EXPECT_TRUE(req6->HasOneAddress("127.0.0.1", 80)); +} + +TEST_F(HostResolverImplDnsTest, BypassDnsTask) { + ChangeDnsConfig(CreateValidDnsConfig()); + + proc_->AddRuleForAllFamilies("", ""); // Default to failures. + + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok.local", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok.local.", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("oklocal", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("oklocal.", 80)->Resolve()); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest("ok", 80)->Resolve()); + + proc_->SignalMultiple(requests_.size()); + + for (size_t i = 0; i < 2; ++i) + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, requests_[i]->WaitForResult()) << i; + + for (size_t i = 2; i < requests_.size(); ++i) + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; +} + +TEST_F(HostResolverImplDnsTest, DisableDnsClientOnPersistentFailure) { + ChangeDnsConfig(CreateValidDnsConfig()); + + proc_->AddRuleForAllFamilies("", ""); // Default to failures. + + // Check that DnsTask works. + Request* req = CreateRequest("ok_1", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); + + for (unsigned i = 0; i < 20; ++i) { + // Use custom names to require separate Jobs. + std::string hostname = base::StringPrintf("err_%u", i); + // Ensure fallback to ProcTask succeeds. + proc_->AddRuleForAllFamilies(hostname, "192.168.1.101"); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()) << i; + } + + proc_->SignalMultiple(requests_.size()); + + for (size_t i = 0; i < requests_.size(); ++i) + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + + ASSERT_FALSE(proc_->HasBlockedRequests()); + + // DnsTask should be disabled by now. + req = CreateRequest("ok_2", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + proc_->SignalMultiple(1u); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->WaitForResult()); + + // Check that it is re-enabled after DNS change. + ChangeDnsConfig(CreateValidDnsConfig()); + req = CreateRequest("ok_3", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); +} + +TEST_F(HostResolverImplDnsTest, DontDisableDnsClientOnSporadicFailure) { + ChangeDnsConfig(CreateValidDnsConfig()); + + // |proc_| defaults to successes. + + // 20 failures interleaved with 20 successes. + for (unsigned i = 0; i < 40; ++i) { + // Use custom names to require separate Jobs. + std::string hostname = (i % 2) == 0 ? base::StringPrintf("err_%u", i) + : base::StringPrintf("ok_%u", i); + EXPECT_EQ(ERR_IO_PENDING, CreateRequest(hostname, 80)->Resolve()) << i; + } + + proc_->SignalMultiple(requests_.size()); + + for (size_t i = 0; i < requests_.size(); ++i) + EXPECT_EQ(OK, requests_[i]->WaitForResult()) << i; + + // Make |proc_| default to failures. + proc_->AddRuleForAllFamilies("", ""); + + // DnsTask should still be enabled. + Request* req = CreateRequest("ok_last", 80); + EXPECT_EQ(ERR_IO_PENDING, req->Resolve()); + EXPECT_EQ(OK, req->WaitForResult()); +} + +} // namespace net diff --git a/net/dns/host_resolver_proc.cc b/net/dns/host_resolver_proc.cc new file mode 100644 index 0000000..6c786a1 --- /dev/null +++ b/net/dns/host_resolver_proc.cc @@ -0,0 +1,251 @@ +// Copyright (c) 2012 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/dns/host_resolver_proc.h" + +#include "build/build_config.h" + +#include "base/logging.h" +#include "base/sys_byteorder.h" +#include "net/base/address_list.h" +#include "net/base/dns_reloader.h" +#include "net/base/net_errors.h" +#include "net/base/sys_addrinfo.h" + +#if defined(OS_OPENBSD) +#define AI_ADDRCONFIG 0 +#endif + +namespace net { + +namespace { + +bool IsAllLocalhostOfOneFamily(const struct addrinfo* ai) { + bool saw_v4_localhost = false; + bool saw_v6_localhost = false; + for (; ai != NULL; ai = ai->ai_next) { + switch (ai->ai_family) { + case AF_INET: { + const struct sockaddr_in* addr_in = + reinterpret_cast(ai->ai_addr); + if ((base::NetToHost32(addr_in->sin_addr.s_addr) & 0xff000000) == + 0x7f000000) + saw_v4_localhost = true; + else + return false; + break; + } + case AF_INET6: { + const struct sockaddr_in6* addr_in6 = + reinterpret_cast(ai->ai_addr); + if (IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr)) + saw_v6_localhost = true; + else + return false; + break; + } + default: + NOTREACHED(); + return false; + } + } + + return saw_v4_localhost != saw_v6_localhost; +} + +} // namespace + +HostResolverProc* HostResolverProc::default_proc_ = NULL; + +HostResolverProc::HostResolverProc(HostResolverProc* previous) { + SetPreviousProc(previous); + + // Implicitly fall-back to the global default procedure. + if (!previous) + SetPreviousProc(default_proc_); +} + +HostResolverProc::~HostResolverProc() { +} + +int HostResolverProc::ResolveUsingPrevious( + const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) { + if (previous_proc_) { + return previous_proc_->Resolve(host, address_family, host_resolver_flags, + addrlist, os_error); + } + + // Final fallback is the system resolver. + return SystemHostResolverProc(host, address_family, host_resolver_flags, + addrlist, os_error); +} + +void HostResolverProc::SetPreviousProc(HostResolverProc* proc) { + HostResolverProc* current_previous = previous_proc_; + previous_proc_ = NULL; + // Now that we've guaranteed |this| is the last proc in a chain, we can + // detect potential cycles using GetLastProc(). + previous_proc_ = (GetLastProc(proc) == this) ? current_previous : proc; +} + +void HostResolverProc::SetLastProc(HostResolverProc* proc) { + GetLastProc(this)->SetPreviousProc(proc); +} + +// static +HostResolverProc* HostResolverProc::GetLastProc(HostResolverProc* proc) { + if (proc == NULL) + return NULL; + HostResolverProc* last_proc = proc; + while (last_proc->previous_proc_ != NULL) + last_proc = last_proc->previous_proc_; + return last_proc; +} + +// static +HostResolverProc* HostResolverProc::SetDefault(HostResolverProc* proc) { + HostResolverProc* old = default_proc_; + default_proc_ = proc; + return old; +} + +// static +HostResolverProc* HostResolverProc::GetDefault() { + return default_proc_; +} + +int SystemHostResolverProc(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) { + if (os_error) + *os_error = 0; + + struct addrinfo* ai = NULL; + struct addrinfo hints = {0}; + + switch (address_family) { + case ADDRESS_FAMILY_IPV4: + hints.ai_family = AF_INET; + break; + case ADDRESS_FAMILY_IPV6: + hints.ai_family = AF_INET6; + break; + case ADDRESS_FAMILY_UNSPECIFIED: + hints.ai_family = AF_UNSPEC; + break; + default: + NOTREACHED(); + hints.ai_family = AF_UNSPEC; + } + +#if defined(OS_WIN) + // DO NOT USE AI_ADDRCONFIG ON WINDOWS. + // + // The following comment in 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. + // + // OpenBSD does not support it, either. + hints.ai_flags = 0; +#else + hints.ai_flags = AI_ADDRCONFIG; +#endif + + // On Linux AI_ADDRCONFIG doesn't consider loopback addreses, even if only + // loopback addresses are configured. So don't use it when there are only + // loopback addresses. + if (host_resolver_flags & HOST_RESOLVER_LOOPBACK_ONLY) + hints.ai_flags &= ~AI_ADDRCONFIG; + + if (host_resolver_flags & HOST_RESOLVER_CANONNAME) + hints.ai_flags |= AI_CANONNAME; + + // Restrict result set to only this socket type to avoid duplicates. + hints.ai_socktype = SOCK_STREAM; + +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ + !defined(OS_ANDROID) + DnsReloaderMaybeReload(); +#endif + int err = getaddrinfo(host.c_str(), NULL, &hints, &ai); + bool should_retry = false; + // If the lookup was restricted (either by address family, or address + // detection), and the results where all localhost of a single family, + // maybe we should retry. There were several bugs related to these + // issues, for example http://crbug.com/42058 and http://crbug.com/49024 + if ((hints.ai_family != AF_UNSPEC || hints.ai_flags & AI_ADDRCONFIG) && + err == 0 && IsAllLocalhostOfOneFamily(ai)) { + if (host_resolver_flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) { + hints.ai_family = AF_UNSPEC; + should_retry = true; + } + if (hints.ai_flags & AI_ADDRCONFIG) { + hints.ai_flags &= ~AI_ADDRCONFIG; + should_retry = true; + } + } + if (should_retry) { + if (ai != NULL) { + freeaddrinfo(ai); + ai = NULL; + } + err = getaddrinfo(host.c_str(), NULL, &hints, &ai); + } + + if (err) { +#if defined(OS_WIN) + err = WSAGetLastError(); +#endif + + // Return the OS error to the caller. + if (os_error) + *os_error = err; + + // If the call to getaddrinfo() failed because of a system error, report + // it separately from ERR_NAME_NOT_RESOLVED. +#if defined(OS_WIN) + if (err != WSAHOST_NOT_FOUND && err != WSANO_DATA) + return ERR_NAME_RESOLUTION_FAILED; +#elif defined(OS_POSIX) && !defined(OS_FREEBSD) + if (err != EAI_NONAME && err != EAI_NODATA) + return ERR_NAME_RESOLUTION_FAILED; +#endif + + return ERR_NAME_NOT_RESOLVED; + } + +#if defined(OS_ANDROID) + // Workaround for Android's getaddrinfo leaving ai==NULL without an error. + // http://crbug.com/134142 + if (ai == NULL) + return ERR_NAME_NOT_RESOLVED; +#endif + + *addrlist = AddressList::CreateFromAddrinfo(ai); + freeaddrinfo(ai); + return OK; +} + +} // namespace net diff --git a/net/dns/host_resolver_proc.h b/net/dns/host_resolver_proc.h new file mode 100644 index 0000000..b4fc0fa --- /dev/null +++ b/net/dns/host_resolver_proc.h @@ -0,0 +1,96 @@ +// Copyright (c) 2012 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_DNS_HOST_RESOLVER_PROC_H_ +#define NET_DNS_HOST_RESOLVER_PROC_H_ + +#include + +#include "base/memory/ref_counted.h" +#include "net/base/address_family.h" +#include "net/base/net_export.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 NET_EXPORT HostResolverProc + : public base::RefCountedThreadSafe { + public: + explicit HostResolverProc(HostResolverProc* previous); + + // Resolves |host| to an address list, restricting the results to addresses + // in |address_family|. If successful returns OK and fills |addrlist| with + // a list of socket addresses. Otherwise returns a network error code, and + // fills |os_error| with a more specific error if it was non-NULL. + virtual int Resolve(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) = 0; + + protected: + friend class base::RefCountedThreadSafe; + + virtual ~HostResolverProc(); + + // Asks the fallback procedure (if set) to do the resolve. + int ResolveUsingPrevious(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error); + + private: + friend class HostResolverImpl; + friend class MockHostResolverBase; + friend class ScopedDefaultHostResolverProc; + + // Sets the previous procedure in the chain. Aborts if this would result in a + // cycle. + void SetPreviousProc(HostResolverProc* proc); + + // Sets the last procedure in the chain, i.e. appends |proc| to the end of the + // current chain. Aborts if this would result in a cycle. + void SetLastProc(HostResolverProc* proc); + + // Returns the last procedure in the chain starting at |proc|. Will return + // NULL iff |proc| is NULL. + static HostResolverProc* GetLastProc(HostResolverProc* 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(); + + scoped_refptr 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, and fills |os_error| with a more specific error if it +// was non-NULL. +NET_EXPORT_PRIVATE int SystemHostResolverProc( + const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error); + +} // namespace net + +#endif // NET_DNS_HOST_RESOLVER_PROC_H_ diff --git a/net/dns/mapped_host_resolver.cc b/net/dns/mapped_host_resolver.cc new file mode 100644 index 0000000..c905b34 --- /dev/null +++ b/net/dns/mapped_host_resolver.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2012 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/dns/mapped_host_resolver.h" + +#include "base/string_util.h" +#include "net/base/host_port_pair.h" +#include "net/base/net_errors.h" +#include "net/base/net_util.h" + +namespace net { + +MappedHostResolver::MappedHostResolver(scoped_ptr impl) + : impl_(impl.Pass()) { +} + +MappedHostResolver::~MappedHostResolver() { +} + +int MappedHostResolver::Resolve(const RequestInfo& original_info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) { + RequestInfo info = original_info; + int rv = ApplyRules(&info); + if (rv != OK) + return rv; + + return impl_->Resolve(info, addresses, callback, out_req, net_log); +} + +int MappedHostResolver::ResolveFromCache(const RequestInfo& original_info, + AddressList* addresses, + const BoundNetLog& net_log) { + RequestInfo info = original_info; + int rv = ApplyRules(&info); + if (rv != OK) + return rv; + + return impl_->ResolveFromCache(info, addresses, net_log); +} + +void MappedHostResolver::CancelRequest(RequestHandle req) { + impl_->CancelRequest(req); +} + +void MappedHostResolver::ProbeIPv6Support() { + impl_->ProbeIPv6Support(); +} + +HostCache* MappedHostResolver::GetHostCache() { + return impl_->GetHostCache(); +} + +int MappedHostResolver::ApplyRules(RequestInfo* info) const { + HostPortPair host_port(info->host_port_pair()); + if (rules_.RewriteHost(&host_port)) { + if (host_port.host() == "~NOTFOUND") + return ERR_NAME_NOT_RESOLVED; + info->set_host_port_pair(host_port); + } + return OK; +} + +} // namespace net diff --git a/net/dns/mapped_host_resolver.h b/net/dns/mapped_host_resolver.h new file mode 100644 index 0000000..db64689 --- /dev/null +++ b/net/dns/mapped_host_resolver.h @@ -0,0 +1,72 @@ +// Copyright (c) 2012 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_DNS_MAPPED_HOST_RESOLVER_H_ +#define NET_DNS_MAPPED_HOST_RESOLVER_H_ + +#include + +#include "base/memory/scoped_ptr.h" +#include "net/base/host_mapping_rules.h" +#include "net/base/net_export.h" +#include "net/dns/host_resolver.h" + +namespace net { + +// This class wraps an existing HostResolver instance, but modifies the +// request before passing it off to |impl|. This is different from +// MockHostResolver which does the remapping at the HostResolverProc +// layer, so it is able to preserve the effectiveness of the cache. +class NET_EXPORT MappedHostResolver : public HostResolver { + public: + // Creates a MappedHostResolver that forwards all of its requests through + // |impl|. + explicit MappedHostResolver(scoped_ptr impl); + virtual ~MappedHostResolver(); + + // Adds a rule to this mapper. The format of the rule can be one of: + // + // "MAP" [":" ] + // "EXCLUDE" + // + // The can be either a hostname, or an IP address literal, + // or "~NOTFOUND". If it is "~NOTFOUND" then all matched hostnames will fail + // to be resolved with ERR_NAME_NOT_RESOLVED. + // + // Returns true if the rule was successfully parsed and added. + bool AddRuleFromString(const std::string& rule_string) { + return rules_.AddRuleFromString(rule_string); + } + + // Takes a comma separated list of rules, and assigns them to this resolver. + void SetRulesFromString(const std::string& rules_string) { + rules_.SetRulesFromString(rules_string); + } + + // HostResolver methods: + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) OVERRIDE; + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) OVERRIDE; + virtual void CancelRequest(RequestHandle req) OVERRIDE; + virtual void ProbeIPv6Support() OVERRIDE; + virtual HostCache* GetHostCache() OVERRIDE; + + private: + // Modify the request |info| according to |rules_|. Returns either OK or + // the network error code that the hostname's resolution mapped to. + int ApplyRules(RequestInfo* info) const; + + scoped_ptr impl_; + + HostMappingRules rules_; +}; + +} // namespace net + +#endif // NET_DNS_MAPPED_HOST_RESOLVER_H_ diff --git a/net/dns/mapped_host_resolver_unittest.cc b/net/dns/mapped_host_resolver_unittest.cc new file mode 100644 index 0000000..8da95e1 --- /dev/null +++ b/net/dns/mapped_host_resolver_unittest.cc @@ -0,0 +1,219 @@ +// Copyright (c) 2012 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/dns/mapped_host_resolver.h" + +#include "net/base/address_list.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/base/net_util.h" +#include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +std::string FirstAddress(const AddressList& address_list) { + if (address_list.empty()) + return ""; + return address_list.front().ToString(); +} + +TEST(MappedHostResolverTest, Inclusion) { + // Create a mock host resolver, with specific hostname to IP mappings. + scoped_ptr resolver_impl(new MockHostResolver()); + resolver_impl->rules()->AddSimulatedFailure("*google.com"); + resolver_impl->rules()->AddRule("baz.com", "192.168.1.5"); + resolver_impl->rules()->AddRule("foo.com", "192.168.1.8"); + resolver_impl->rules()->AddRule("proxy", "192.168.1.11"); + + // Create a remapped resolver that uses |resolver_impl|. + scoped_ptr resolver( + new MappedHostResolver(resolver_impl.PassAs())); + + int rv; + AddressList address_list; + + // Try resolving "www.google.com:80". There are no mappings yet, so this + // hits |resolver_impl| and fails. + TestCompletionCallback callback; + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.google.com", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); + + // Remap *.google.com to baz.com. + EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com")); + + // Try resolving "www.google.com:80". Should be remapped to "baz.com:80". + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.google.com", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); + + // Try resolving "foo.com:77". This will NOT be remapped, so result + // is "foo.com:77". + rv = resolver->Resolve(HostResolver::RequestInfo(HostPortPair("foo.com", 77)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.8:77", FirstAddress(address_list)); + + // Remap "*.org" to "proxy:99". + EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99")); + + // Try resolving "chromium.org:61". Should be remapped to "proxy:99". + rv = resolver->Resolve(HostResolver::RequestInfo + (HostPortPair("chromium.org", 61)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.11:99", FirstAddress(address_list)); +} + +// Tests that exclusions are respected. +TEST(MappedHostResolverTest, Exclusion) { + // Create a mock host resolver, with specific hostname to IP mappings. + scoped_ptr resolver_impl(new MockHostResolver()); + resolver_impl->rules()->AddRule("baz", "192.168.1.5"); + resolver_impl->rules()->AddRule("www.google.com", "192.168.1.3"); + + // Create a remapped resolver that uses |resolver_impl|. + scoped_ptr resolver( + new MappedHostResolver(resolver_impl.PassAs())); + + int rv; + AddressList address_list; + TestCompletionCallback callback; + + // Remap "*.com" to "baz". + EXPECT_TRUE(resolver->AddRuleFromString("map *.com baz")); + + // Add an exclusion for "*.google.com". + EXPECT_TRUE(resolver->AddRuleFromString("EXCLUDE *.google.com")); + + // Try resolving "www.google.com". Should not be remapped due to exclusion). + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.google.com", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.3:80", FirstAddress(address_list)); + + // Try resolving "chrome.com:80". Should be remapped to "baz:80". + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("chrome.com", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); +} + +TEST(MappedHostResolverTest, SetRulesFromString) { + // Create a mock host resolver, with specific hostname to IP mappings. + scoped_ptr resolver_impl(new MockHostResolver()); + resolver_impl->rules()->AddRule("baz", "192.168.1.7"); + resolver_impl->rules()->AddRule("bar", "192.168.1.9"); + + // Create a remapped resolver that uses |resolver_impl|. + scoped_ptr resolver( + new MappedHostResolver(resolver_impl.PassAs())); + + int rv; + AddressList address_list; + TestCompletionCallback callback; + + // Remap "*.com" to "baz", and *.net to "bar:60". + resolver->SetRulesFromString("map *.com baz , map *.net bar:60"); + + // Try resolving "www.google.com". Should be remapped to "baz". + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.google.com", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.7:80", FirstAddress(address_list)); + + // Try resolving "chrome.net:80". Should be remapped to "bar:60". + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("chrome.net", 80)), + &address_list, callback.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.9:60", FirstAddress(address_list)); +} + +// Parsing bad rules should silently discard the rule (and never crash). +TEST(MappedHostResolverTest, ParseInvalidRules) { + scoped_ptr resolver( + new MappedHostResolver(scoped_ptr())); + + EXPECT_FALSE(resolver->AddRuleFromString("xyz")); + EXPECT_FALSE(resolver->AddRuleFromString("")); + EXPECT_FALSE(resolver->AddRuleFromString(" ")); + EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE")); + EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE foo bar")); + EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE")); + EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x")); + EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x :10")); +} + +// Test mapping hostnames to resolving failures. +TEST(MappedHostResolverTest, MapToError) { + scoped_ptr resolver_impl(new MockHostResolver()); + resolver_impl->rules()->AddRule("*", "192.168.1.5"); + + scoped_ptr resolver( + new MappedHostResolver(resolver_impl.PassAs())); + + int rv; + AddressList address_list; + + // Remap *.google.com to resolving failures. + EXPECT_TRUE(resolver->AddRuleFromString("MAP *.google.com ~NOTFOUND")); + + // Try resolving www.google.com --> Should give an error. + TestCompletionCallback callback1; + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.google.com", 80)), + &address_list, callback1.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); + + // Try resolving www.foo.com --> Should succeed. + TestCompletionCallback callback2; + rv = resolver->Resolve(HostResolver::RequestInfo( + HostPortPair("www.foo.com", 80)), + &address_list, callback2.callback(), NULL, + BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback2.WaitForResult(); + EXPECT_EQ(OK, rv); + EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); +} + +} // namespace + +} // namespace net diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc new file mode 100644 index 0000000..fb03836 --- /dev/null +++ b/net/dns/mock_host_resolver.cc @@ -0,0 +1,417 @@ +// Copyright (c) 2012 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/dns/mock_host_resolver.h" + +#include +#include + +#include "base/bind.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop.h" +#include "base/stl_util.h" +#include "base/string_util.h" +#include "base/strings/string_split.h" +#include "base/threading/platform_thread.h" +#include "net/base/host_cache.h" +#include "net/base/net_errors.h" +#include "net/base/net_util.h" +#include "net/base/test_completion_callback.h" +#if defined(OS_WIN) +#include "net/base/winsock_init.h" +#endif + +namespace net { + +namespace { + +// Cache size for the MockCachingHostResolver. +const unsigned kMaxCacheEntries = 100; +// TTL for the successful resolutions. Failures are not cached. +const unsigned kCacheEntryTTLSeconds = 60; + +} // namespace + +int ParseAddressList(const std::string& host_list, + const std::string& canonical_name, + AddressList* addrlist) { + *addrlist = AddressList(); + std::vector addresses; + base::SplitString(host_list, ',', &addresses); + addrlist->set_canonical_name(canonical_name); + for (size_t index = 0; index < addresses.size(); ++index) { + IPAddressNumber ip_number; + if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) { + LOG(WARNING) << "Not a supported IP literal: " << addresses[index]; + return ERR_UNEXPECTED; + } + addrlist->push_back(IPEndPoint(ip_number, -1)); + } + return OK; +} + +struct MockHostResolverBase::Request { + Request(const RequestInfo& req_info, + AddressList* addr, + const CompletionCallback& cb) + : info(req_info), addresses(addr), callback(cb) {} + RequestInfo info; + AddressList* addresses; + CompletionCallback callback; +}; + +MockHostResolverBase::~MockHostResolverBase() { + STLDeleteValues(&requests_); +} + +int MockHostResolverBase::Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* handle, + const BoundNetLog& net_log) { + DCHECK(CalledOnValidThread()); + num_resolve_++; + size_t id = next_request_id_++; + int rv = ResolveFromIPLiteralOrCache(info, addresses); + if (rv != ERR_DNS_CACHE_MISS) { + return rv; + } + if (synchronous_mode_) { + return ResolveProc(id, info, addresses); + } + // Store the request for asynchronous resolution + Request* req = new Request(info, addresses, callback); + requests_[id] = req; + if (handle) + *handle = reinterpret_cast(id); + + if (!ondemand_mode_) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), id)); + } + + return ERR_IO_PENDING; +} + +int MockHostResolverBase::ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) { + num_resolve_from_cache_++; + DCHECK(CalledOnValidThread()); + next_request_id_++; + int rv = ResolveFromIPLiteralOrCache(info, addresses); + return rv; +} + +void MockHostResolverBase::CancelRequest(RequestHandle handle) { + DCHECK(CalledOnValidThread()); + size_t id = reinterpret_cast(handle); + RequestMap::iterator it = requests_.find(id); + if (it != requests_.end()) { + scoped_ptr req(it->second); + requests_.erase(it); + } else { + NOTREACHED() << "CancelRequest must NOT be called after request is " + "complete or canceled."; + } +} + +HostCache* MockHostResolverBase::GetHostCache() { + return cache_.get(); +} + +void MockHostResolverBase::ResolveAllPending() { + DCHECK(CalledOnValidThread()); + DCHECK(ondemand_mode_); + for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), i->first)); + } +} + +// start id from 1 to distinguish from NULL RequestHandle +MockHostResolverBase::MockHostResolverBase(bool use_caching) + : synchronous_mode_(false), + ondemand_mode_(false), + next_request_id_(1), + num_resolve_(0), + num_resolve_from_cache_(0) { + rules_ = CreateCatchAllHostResolverProc(); + + if (use_caching) { + cache_.reset(new HostCache(kMaxCacheEntries)); + } +} + +int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info, + AddressList* addresses) { + IPAddressNumber ip; + if (ParseIPLiteralToNumber(info.hostname(), &ip)) { + *addresses = AddressList::CreateFromIPAddress(ip, info.port()); + if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME) + addresses->SetDefaultCanonicalName(); + return OK; + } + int rv = ERR_DNS_CACHE_MISS; + if (cache_.get() && info.allow_cached_response()) { + HostCache::Key key(info.hostname(), + info.address_family(), + info.host_resolver_flags()); + const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now()); + if (entry) { + rv = entry->error; + if (rv == OK) + *addresses = AddressList::CopyWithPort(entry->addrlist, info.port()); + } + } + return rv; +} + +int MockHostResolverBase::ResolveProc(size_t id, + const RequestInfo& info, + AddressList* addresses) { + AddressList addr; + int rv = rules_->Resolve(info.hostname(), + info.address_family(), + info.host_resolver_flags(), + &addr, + NULL); + if (cache_.get()) { + HostCache::Key key(info.hostname(), + info.address_family(), + info.host_resolver_flags()); + // Storing a failure with TTL 0 so that it overwrites previous value. + base::TimeDelta ttl; + if (rv == OK) + ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); + cache_->Set(key, HostCache::Entry(rv, addr), base::TimeTicks::Now(), ttl); + } + if (rv == OK) + *addresses = AddressList::CopyWithPort(addr, info.port()); + return rv; +} + +void MockHostResolverBase::ResolveNow(size_t id) { + RequestMap::iterator it = requests_.find(id); + if (it == requests_.end()) + return; // was canceled + + scoped_ptr req(it->second); + requests_.erase(it); + int rv = ResolveProc(id, req->info, req->addresses); + if (!req->callback.is_null()) + req->callback.Run(rv); +} + +//----------------------------------------------------------------------------- + +struct RuleBasedHostResolverProc::Rule { + enum ResolverType { + kResolverTypeFail, + kResolverTypeSystem, + kResolverTypeIPLiteral, + }; + + ResolverType resolver_type; + std::string host_pattern; + AddressFamily address_family; + HostResolverFlags host_resolver_flags; + std::string replacement; + std::string canonical_name; + int latency_ms; // In milliseconds. + + Rule(ResolverType resolver_type, + const std::string& host_pattern, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + const std::string& replacement, + const std::string& canonical_name, + int latency_ms) + : resolver_type(resolver_type), + host_pattern(host_pattern), + address_family(address_family), + host_resolver_flags(host_resolver_flags), + replacement(replacement), + canonical_name(canonical_name), + latency_ms(latency_ms) {} +}; + +RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous) + : HostResolverProc(previous) { +} + +void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern, + const std::string& replacement) { + AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED, + replacement); +} + +void RuleBasedHostResolverProc::AddRuleForAddressFamily( + const std::string& host_pattern, + AddressFamily address_family, + const std::string& replacement) { + DCHECK(!replacement.empty()); + HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags, + replacement, "", 0); + rules_.push_back(rule); +} + +void RuleBasedHostResolverProc::AddIPLiteralRule( + const std::string& host_pattern, + const std::string& ip_literal, + const std::string& canonical_name) { + // Literals are always resolved to themselves by HostResolverImpl, + // consequently we do not support remapping them. + IPAddressNumber ip_number; + DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number)); + HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + if (!canonical_name.empty()) + flags |= HOST_RESOLVER_CANONNAME; + Rule rule(Rule::kResolverTypeIPLiteral, host_pattern, + ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name, + 0); + rules_.push_back(rule); +} + +void RuleBasedHostResolverProc::AddRuleWithLatency( + const std::string& host_pattern, + const std::string& replacement, + int latency_ms) { + DCHECK(!replacement.empty()); + HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, + flags, replacement, "", latency_ms); + rules_.push_back(rule); +} + +void RuleBasedHostResolverProc::AllowDirectLookup( + const std::string& host_pattern) { + HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, + flags, "", "", 0); + rules_.push_back(rule); +} + +void RuleBasedHostResolverProc::AddSimulatedFailure( + const std::string& host_pattern) { + HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY | + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; + Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED, + flags, "", "", 0); + rules_.push_back(rule); +} + +void RuleBasedHostResolverProc::ClearRules() { + rules_.clear(); +} + +int RuleBasedHostResolverProc::Resolve(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) { + RuleList::iterator r; + for (r = rules_.begin(); r != rules_.end(); ++r) { + bool matches_address_family = + r->address_family == ADDRESS_FAMILY_UNSPECIFIED || + r->address_family == address_family; + // Flags match if all of the bitflags in host_resolver_flags are enabled + // in the rule's host_resolver_flags. However, the rule may have additional + // flags specified, in which case the flags should still be considered a + // match. + bool matches_flags = (r->host_resolver_flags & host_resolver_flags) == + host_resolver_flags; + if (matches_flags && matches_address_family && + MatchPattern(host, r->host_pattern)) { + if (r->latency_ms != 0) { + base::PlatformThread::Sleep( + base::TimeDelta::FromMilliseconds(r->latency_ms)); + } + + // Remap to a new host. + const std::string& effective_host = + r->replacement.empty() ? host : r->replacement; + + // Apply the resolving function to the remapped hostname. + switch (r->resolver_type) { + case Rule::kResolverTypeFail: + return ERR_NAME_NOT_RESOLVED; + case Rule::kResolverTypeSystem: +#if defined(OS_WIN) + net::EnsureWinsockInit(); +#endif + return SystemHostResolverProc(effective_host, + address_family, + host_resolver_flags, + addrlist, os_error); + case Rule::kResolverTypeIPLiteral: + return ParseAddressList(effective_host, + r->canonical_name, + addrlist); + default: + NOTREACHED(); + return ERR_UNEXPECTED; + } + } + } + return ResolveUsingPrevious(host, address_family, + host_resolver_flags, addrlist, os_error); +} + +RuleBasedHostResolverProc::~RuleBasedHostResolverProc() { +} + +RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() { + RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL); + catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost"); + + // Next add a rules-based layer the use controls. + return new RuleBasedHostResolverProc(catchall); +} + +//----------------------------------------------------------------------------- + +int HangingHostResolver::Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) { + return ERR_IO_PENDING; +} + +int HangingHostResolver::ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) { + return ERR_DNS_CACHE_MISS; +} + +//----------------------------------------------------------------------------- + +ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {} + +ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc( + HostResolverProc* proc) { + Init(proc); +} + +ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() { + HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_); + // The lifetimes of multiple instances must be nested. + CHECK_EQ(old_proc, current_proc_); +} + +void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) { + current_proc_ = proc; + previous_proc_ = HostResolverProc::SetDefault(current_proc_); + current_proc_->SetLastProc(previous_proc_); +} + +} // namespace net diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h new file mode 100644 index 0000000..d22e800c --- /dev/null +++ b/net/dns/mock_host_resolver.h @@ -0,0 +1,254 @@ +// Copyright (c) 2011 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_DNS_MOCK_HOST_RESOLVER_H_ +#define NET_DNS_MOCK_HOST_RESOLVER_H_ + +#include +#include + +#include "base/memory/weak_ptr.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/non_thread_safe.h" +#include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_proc.h" + +namespace net { + +class HostCache; +class RuleBasedHostResolverProc; + +// Fills |*addrlist| with a socket address for |host_list| which should be a +// comma-separated list of IPv4 or IPv6 literal(s) without enclosing brackets. +// If |canonical_name| is non-empty it is used as the DNS canonical name for +// the host. Returns OK on success, ERR_UNEXPECTED otherwise. +int ParseAddressList(const std::string& host_list, + const std::string& canonical_name, + AddressList* addrlist); + +// In most cases, it is important that unit tests avoid relying on 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. +// +// By default, MockHostResolvers include a single rule that maps all hosts to +// 127.0.0.1. + +// Base class shared by MockHostResolver and MockCachingHostResolver. +class MockHostResolverBase : public HostResolver, + public base::SupportsWeakPtr, + public base::NonThreadSafe { + public: + virtual ~MockHostResolverBase(); + + RuleBasedHostResolverProc* rules() { return rules_; } + void set_rules(RuleBasedHostResolverProc* rules) { rules_ = rules; } + + // Controls whether resolutions complete synchronously or asynchronously. + void set_synchronous_mode(bool is_synchronous) { + synchronous_mode_ = is_synchronous; + } + + // Asynchronous requests are automatically resolved by default. + // If set_ondemand_mode() is set then Resolve() returns IO_PENDING and + // ResolveAllPending() must be explicitly invoked to resolve all requests + // that are pending. + void set_ondemand_mode(bool is_ondemand) { + ondemand_mode_ = is_ondemand; + } + + // HostResolver methods: + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) OVERRIDE; + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) OVERRIDE; + virtual void CancelRequest(RequestHandle req) OVERRIDE; + virtual HostCache* GetHostCache() OVERRIDE; + + // Resolves all pending requests. It is only valid to invoke this if + // set_ondemand_mode was set before. The requests are resolved asynchronously, + // after this call returns. + void ResolveAllPending(); + + // Returns true if there are pending requests that can be resolved by invoking + // ResolveAllPending(). + bool has_pending_requests() const { return !requests_.empty(); } + + // The number of times that Resolve() has been called. + size_t num_resolve() const { + return num_resolve_; + } + + // The number of times that ResolveFromCache() has been called. + size_t num_resolve_from_cache() const { + return num_resolve_from_cache_; + } + + protected: + explicit MockHostResolverBase(bool use_caching); + + private: + struct Request; + typedef std::map RequestMap; + + // Resolve as IP or from |cache_| return cached error or + // DNS_CACHE_MISS if failed. + int ResolveFromIPLiteralOrCache(const RequestInfo& info, + AddressList* addresses); + // Resolve via |proc_|. + int ResolveProc(size_t id, const RequestInfo& info, AddressList* addresses); + // Resolve request stored in |requests_|. Pass rv to callback. + void ResolveNow(size_t id); + + bool synchronous_mode_; + bool ondemand_mode_; + scoped_refptr rules_; + scoped_ptr cache_; + RequestMap requests_; + size_t next_request_id_; + + size_t num_resolve_; + size_t num_resolve_from_cache_; + + DISALLOW_COPY_AND_ASSIGN(MockHostResolverBase); +}; + +class MockHostResolver : public MockHostResolverBase { + public: + MockHostResolver() : MockHostResolverBase(false /*use_caching*/) {} + virtual ~MockHostResolver() {} +}; + +// Same as MockHostResolver, except internally it uses a host-cache. +// +// Note that tests are advised to use MockHostResolver instead, since it is +// more predictable. (MockHostResolver also can be put into synchronous +// operation mode in case that is what you needed from the caching version). +class MockCachingHostResolver : public MockHostResolverBase { + public: + MockCachingHostResolver() : MockHostResolverBase(true /*use_caching*/) {} + virtual ~MockCachingHostResolver() {} +}; + +// 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); + + // 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); + + // Same as AddRule(), but further restricts to |address_family|. + void AddRuleForAddressFamily(const std::string& host_pattern, + AddressFamily address_family, + const std::string& replacement); + + // Same as AddRule(), but the replacement is expected to be an IPv4 or IPv6 + // literal. This can be used in place of AddRule() to bypass the system's + // host resolver (the address list will be constructed manually). + // If |canonical_name| is non-empty, it is copied to the resulting AddressList + // but does not impact DNS resolution. + // |ip_literal| can be a single IP address like "192.168.1.1" or a comma + // separated list of IP addresses, like "::1,192:168.1.2". + void AddIPLiteralRule(const std::string& host_pattern, + const std::string& ip_literal, + const std::string& canonical_name); + + 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); + + // Deletes all the rules that have been added. + void ClearRules(); + + // HostResolverProc methods: + virtual int Resolve(const std::string& host, + AddressFamily address_family, + HostResolverFlags host_resolver_flags, + AddressList* addrlist, + int* os_error) OVERRIDE; + + private: + struct Rule; + typedef std::list RuleList; + + virtual ~RuleBasedHostResolverProc(); + + RuleList rules_; +}; + +// Create rules that map all requests to localhost. +RuleBasedHostResolverProc* CreateCatchAllHostResolverProc(); + +// HangingHostResolver never completes its |Resolve| request. +class HangingHostResolver : public HostResolver { + public: + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) OVERRIDE; + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) OVERRIDE; + virtual void CancelRequest(RequestHandle req) OVERRIDE {} +}; + +// This class sets the default HostResolverProc for a particular scope. The +// chain of resolver procs starting at |proc| is placed in front of any existing +// default resolver proc(s). This means that if multiple +// ScopedDefaultHostResolverProcs are declared, then resolving will start with +// the procs given to the last-allocated one, then fall back to the procs given +// to the previously-allocated one, and so forth. +// +// 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 current_proc_; + scoped_refptr previous_proc_; +}; + +} // namespace net + +#endif // NET_DNS_MOCK_HOST_RESOLVER_H_ diff --git a/net/dns/single_request_host_resolver.cc b/net/dns/single_request_host_resolver.cc new file mode 100644 index 0000000..e926e86 --- /dev/null +++ b/net/dns/single_request_host_resolver.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 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/dns/single_request_host_resolver.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "net/base/net_errors.h" + +namespace net { + +SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver) + : resolver_(resolver), + cur_request_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST(callback_( + base::Bind(&SingleRequestHostResolver::OnResolveCompletion, + base::Unretained(this)))) { + DCHECK(resolver_ != NULL); +} + +SingleRequestHostResolver::~SingleRequestHostResolver() { + Cancel(); +} + +int SingleRequestHostResolver::Resolve( + const HostResolver::RequestInfo& info, AddressList* addresses, + const CompletionCallback& callback, const BoundNetLog& net_log) { + DCHECK(addresses); + DCHECK_EQ(false, callback.is_null()); + DCHECK(cur_request_callback_.is_null()) << "resolver already in use"; + + HostResolver::RequestHandle request = NULL; + + // We need to be notified of completion before |callback| is called, so that + // we can clear out |cur_request_*|. + CompletionCallback transient_callback = + callback.is_null() ? CompletionCallback() : callback_; + + int rv = resolver_->Resolve( + info, addresses, transient_callback, &request, net_log); + + if (rv == ERR_IO_PENDING) { + DCHECK_EQ(false, callback.is_null()); + // Cleared in OnResolveCompletion(). + cur_request_ = request; + cur_request_callback_ = callback; + } + + return rv; +} + +void SingleRequestHostResolver::Cancel() { + if (!cur_request_callback_.is_null()) { + resolver_->CancelRequest(cur_request_); + cur_request_ = NULL; + cur_request_callback_.Reset(); + } +} + +void SingleRequestHostResolver::OnResolveCompletion(int result) { + DCHECK(cur_request_); + DCHECK_EQ(false, cur_request_callback_.is_null()); + + CompletionCallback callback = cur_request_callback_; + + // Clear the outstanding request information. + cur_request_ = NULL; + cur_request_callback_.Reset(); + + // Call the user's original callback. + callback.Run(result); +} + +} // namespace net diff --git a/net/dns/single_request_host_resolver.h b/net/dns/single_request_host_resolver.h new file mode 100644 index 0000000..52d0132 --- /dev/null +++ b/net/dns/single_request_host_resolver.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 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_DNS_SINGLE_REQUEST_HOST_RESOLVER_H_ +#define NET_DNS_SINGLE_REQUEST_HOST_RESOLVER_H_ + +#include "net/dns/host_resolver.h" + +namespace net { + +// This class represents the task of resolving a hostname (or IP address +// literal) to an AddressList object. It wraps HostResolver to resolve only a +// single hostname at a time and cancels this request when going out of scope. +class NET_EXPORT SingleRequestHostResolver { + public: + // |resolver| must remain valid for the lifetime of |this|. + explicit SingleRequestHostResolver(HostResolver* resolver); + + // If a completion callback is pending when the resolver is destroyed, the + // host resolution is cancelled, and the completion callback will not be + // called. + ~SingleRequestHostResolver(); + + // Resolves the given hostname (or IP address literal), filling out the + // |addresses| object upon success. See HostResolver::Resolve() for details. + int Resolve(const HostResolver::RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + const BoundNetLog& net_log); + + // Cancels the in-progress request, if any. This prevents the callback + // from being invoked. Resolve() can be called again after cancelling. + void Cancel(); + + private: + // Callback for when the request to |resolver_| completes, so we dispatch + // to the user's callback. + void OnResolveCompletion(int result); + + // The actual host resolver that will handle the request. + HostResolver* const resolver_; + + // The current request (if any). + HostResolver::RequestHandle cur_request_; + CompletionCallback cur_request_callback_; + + // Completion callback for when request to |resolver_| completes. + CompletionCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(SingleRequestHostResolver); +}; + +} // namespace net + +#endif // NET_DNS_SINGLE_REQUEST_HOST_RESOLVER_H_ diff --git a/net/dns/single_request_host_resolver_unittest.cc b/net/dns/single_request_host_resolver_unittest.cc new file mode 100644 index 0000000..3e2ea1e --- /dev/null +++ b/net/dns/single_request_host_resolver_unittest.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2012 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/dns/single_request_host_resolver.h" + +#include "net/base/address_list.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +// Helper class used by SingleRequestHostResolverTest.Cancel test. +// It checks that only one request is outstanding at a time, and that +// it is cancelled before the class is destroyed. +class HangingHostResolver : public HostResolver { + public: + HangingHostResolver() : outstanding_request_(NULL) {} + + virtual ~HangingHostResolver() { + EXPECT_TRUE(!has_outstanding_request()); + } + + bool has_outstanding_request() const { + return outstanding_request_ != NULL; + } + + virtual int Resolve(const RequestInfo& info, + AddressList* addresses, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) OVERRIDE { + EXPECT_FALSE(has_outstanding_request()); + outstanding_request_ = reinterpret_cast(0x1234); + *out_req = outstanding_request_; + + // Never complete this request! Caller is expected to cancel it + // before destroying the resolver. + return ERR_IO_PENDING; + } + + virtual int ResolveFromCache(const RequestInfo& info, + AddressList* addresses, + const BoundNetLog& net_log) OVERRIDE { + NOTIMPLEMENTED(); + return ERR_UNEXPECTED; + } + + virtual void CancelRequest(RequestHandle req) OVERRIDE { + EXPECT_TRUE(has_outstanding_request()); + EXPECT_EQ(req, outstanding_request_); + outstanding_request_ = NULL; + } + + private: + RequestHandle outstanding_request_; + + DISALLOW_COPY_AND_ASSIGN(HangingHostResolver); +}; + +// Test that a regular end-to-end lookup returns the expected result. +TEST(SingleRequestHostResolverTest, NormalResolve) { + // Create a host resolver dependency that returns address "199.188.1.166" + // for resolutions of "watsup". + MockHostResolver resolver; + resolver.rules()->AddIPLiteralRule("watsup", "199.188.1.166", ""); + + SingleRequestHostResolver single_request_resolver(&resolver); + + // Resolve "watsup:90" using our SingleRequestHostResolver. + AddressList addrlist; + TestCompletionCallback callback; + HostResolver::RequestInfo request(HostPortPair("watsup", 90)); + int rv = single_request_resolver.Resolve( + request, &addrlist, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + + // Verify that the result is what we specified in the MockHostResolver. + ASSERT_FALSE(addrlist.empty()); + EXPECT_EQ("199.188.1.166", addrlist.front().ToStringWithoutPort()); +} + +// Test that the Cancel() method cancels any outstanding request. +TEST(SingleRequestHostResolverTest, Cancel) { + HangingHostResolver resolver; + + { + SingleRequestHostResolver single_request_resolver(&resolver); + + // Resolve "watsup:90" using our SingleRequestHostResolver. + AddressList addrlist; + TestCompletionCallback callback; + HostResolver::RequestInfo request(HostPortPair("watsup", 90)); + int rv = single_request_resolver.Resolve( + request, &addrlist, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_TRUE(resolver.has_outstanding_request()); + } + + // Now that the SingleRequestHostResolver has been destroyed, the + // in-progress request should have been aborted. + EXPECT_FALSE(resolver.has_outstanding_request()); +} + +// Test that the Cancel() method is a no-op when there is no outstanding +// request. +TEST(SingleRequestHostResolverTest, CancelWhileNoPendingRequest) { + HangingHostResolver resolver; + SingleRequestHostResolver single_request_resolver(&resolver); + single_request_resolver.Cancel(); + + // To pass, HangingHostResolver should not have received a cancellation + // request (since there is nothing to cancel). If it does, it will crash. +} + +} // namespace + +} // namespace net diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h index e425c36..5eb6aae7 100644 --- a/net/ftp/ftp_network_transaction.h +++ b/net/ftp/ftp_network_transaction.h @@ -13,9 +13,9 @@ #include "base/memory/scoped_ptr.h" #include "net/base/address_list.h" #include "net/base/auth.h" -#include "net/base/host_resolver.h" #include "net/base/net_log.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/ftp/ftp_ctrl_response_buffer.h" #include "net/ftp/ftp_response_info.h" #include "net/ftp/ftp_transaction.h" diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index c9ddb66..efc5143 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc @@ -13,9 +13,9 @@ #include "base/utf_string_conversions.h" #include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_util.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/ftp/ftp_network_session.h" #include "net/ftp/ftp_request_info.h" #include "net/socket/socket_test_util.h" diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index 1ab12ad..0dcb5bb 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc @@ -11,8 +11,8 @@ #include "base/threading/platform_thread.h" #include "base/utf_string_conversions.h" #include "net/base/auth.h" -#include "net/base/host_resolver.h" #include "net/base/net_util.h" +#include "net/dns/host_resolver.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" diff --git a/net/http/http_auth_handler_factory_unittest.cc b/net/http/http_auth_handler_factory_unittest.cc index cc5c6d4..8e69919 100644 --- a/net/http/http_auth_handler_factory_unittest.cc +++ b/net/http/http_auth_handler_factory_unittest.cc @@ -3,8 +3,8 @@ // found in the LICENSE file. #include "base/memory/scoped_ptr.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/mock_allow_url_security_manager.h" diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index 35681c4..f509d90 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc @@ -11,9 +11,9 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "net/base/address_family.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/http/http_auth_filter.h" #include "net/http/url_security_manager.h" diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index 4d8eaf4..9891c20 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc @@ -6,9 +6,9 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_request_info.h" #include "net/http/mock_allow_url_security_manager.h" #if defined(OS_WIN) diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc index e70cb0d..88c7f95 100644 --- a/net/http/http_auth_unittest.cc +++ b/net/http/http_auth_unittest.cc @@ -8,8 +8,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/string_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth.h" #include "net/http/http_auth_filter.h" #include "net/http/http_auth_handler.h" diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index ac052de..b0bfd79 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -5,8 +5,8 @@ #include "net/http/http_network_layer.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" #include "net/http/http_transaction_unittest.h" diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index db9d762..f095ad6 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -9,8 +9,8 @@ #include "base/memory/ref_counted.h" #include "base/threading/non_thread_safe.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/net_export.h" +#include "net/dns/host_resolver.h" #include "net/http/http_auth_cache.h" #include "net/http/http_stream_factory.h" #include "net/quic/quic_stream_factory.h" diff --git a/net/http/http_network_transaction_spdy2_unittest.cc b/net/http/http_network_transaction_spdy2_unittest.cc index 74e4a464..e773011 100644 --- a/net/http/http_network_transaction_spdy2_unittest.cc +++ b/net/http/http_network_transaction_spdy2_unittest.cc @@ -27,7 +27,6 @@ #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" #include "net/base/request_priority.h" @@ -36,6 +35,7 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_digest.h" #include "net/http/http_auth_handler_mock.h" #include "net/http/http_auth_handler_ntlm.h" diff --git a/net/http/http_network_transaction_spdy3_unittest.cc b/net/http/http_network_transaction_spdy3_unittest.cc index e2a262e..8bc44db 100644 --- a/net/http/http_network_transaction_spdy3_unittest.cc +++ b/net/http/http_network_transaction_spdy3_unittest.cc @@ -27,7 +27,6 @@ #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" #include "net/base/request_priority.h" @@ -36,6 +35,7 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_digest.h" #include "net/http/http_auth_handler_mock.h" #include "net/http/http_auth_handler_ntlm.h" diff --git a/net/http/http_pipelined_network_transaction_unittest.cc b/net/http/http_pipelined_network_transaction_unittest.cc index 1976d6a..d13c31e 100644 --- a/net/http/http_pipelined_network_transaction_unittest.cc +++ b/net/http/http_pipelined_network_transaction_unittest.cc @@ -12,10 +12,10 @@ #include "net/base/address_list.h" #include "net/base/host_cache.h" #include "net/base/io_buffer.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/base/request_priority.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_mock.h" #include "net/http/http_network_session.h" #include "net/http/http_network_transaction.h" diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc index a7ece96..f720e4f 100644 --- a/net/http/http_stream_factory_impl_unittest.cc +++ b/net/http/http_stream_factory_impl_unittest.cc @@ -8,9 +8,9 @@ #include "base/basictypes.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" #include "net/http/http_network_session_peer.h" diff --git a/net/net.gyp b/net/net.gyp index f66d8f6..0b43937 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -170,12 +170,6 @@ 'base/host_mapping_rules.h', 'base/host_port_pair.cc', 'base/host_port_pair.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/ip_endpoint.cc', @@ -193,8 +187,6 @@ 'base/load_states_list.h', 'base/load_timing_info.cc', 'base/load_timing_info.h', - 'base/mapped_host_resolver.cc', - 'base/mapped_host_resolver.h', 'base/mime_sniffer.cc', 'base/mime_sniffer.h', 'base/mime_util.cc', @@ -259,8 +251,6 @@ 'base/sdch_manager.h', 'base/single_request_cert_verifier.cc', 'base/single_request_cert_verifier.h', - 'base/single_request_host_resolver.cc', - 'base/single_request_host_resolver.h', 'base/static_cookie_policy.cc', 'base/static_cookie_policy.h', 'base/stream_listen_socket.cc', @@ -432,10 +422,20 @@ 'dns/dns_socket_pool.h', 'dns/dns_transaction.cc', 'dns/dns_transaction.h', + 'dns/host_resolver.cc', + 'dns/host_resolver.h', + 'dns/host_resolver_impl.cc', + 'dns/host_resolver_impl.h', + 'dns/host_resolver_proc.cc', + 'dns/host_resolver_proc.h', + 'dns/mapped_host_resolver.cc', + 'dns/mapped_host_resolver.h', 'dns/notify_watcher_mac.cc', 'dns/notify_watcher_mac.h', 'dns/serial_worker.cc', 'dns/serial_worker.h', + 'dns/single_request_host_resolver.cc', + 'dns/single_request_host_resolver.h', 'ftp/ftp_auth_cache.cc', 'ftp/ftp_auth_cache.h', 'ftp/ftp_ctrl_response_buffer.cc', @@ -1391,10 +1391,8 @@ 'base/host_cache_unittest.cc', 'base/host_mapping_rules_unittest.cc', 'base/host_port_pair_unittest.cc', - 'base/host_resolver_impl_unittest.cc', 'base/ip_endpoint_unittest.cc', 'base/keygen_handler_unittest.cc', - 'base/mapped_host_resolver_unittest.cc', 'base/mime_sniffer_unittest.cc', 'base/mime_util_unittest.cc', 'base/mock_filter_context.cc', @@ -1410,7 +1408,6 @@ 'base/priority_queue_unittest.cc', 'base/registry_controlled_domains/registry_controlled_domain_unittest.cc', 'base/sdch_filter_unittest.cc', - 'base/single_request_host_resolver_unittest.cc', 'base/static_cookie_policy_unittest.cc', 'base/tcp_listen_socket_unittest.cc', 'base/tcp_listen_socket_unittest.h', @@ -1453,7 +1450,10 @@ 'dns/dns_response_unittest.cc', 'dns/dns_session_unittest.cc', 'dns/dns_transaction_unittest.cc', + 'dns/host_resolver_impl_unittest.cc', + 'dns/mapped_host_resolver_unittest.cc', 'dns/serial_worker_unittest.cc', + 'dns/single_request_host_resolver_unittest.cc', 'ftp/ftp_auth_cache_unittest.cc', 'ftp/ftp_ctrl_response_buffer_unittest.cc', 'ftp/ftp_directory_listing_parser_ls_unittest.cc', @@ -1982,8 +1982,6 @@ 'base/mock_cert_verifier.h', 'base/mock_file_stream.cc', 'base/mock_file_stream.h', - 'base/mock_host_resolver.cc', - 'base/mock_host_resolver.h', 'base/test_completion_callback.cc', 'base/test_completion_callback.h', 'base/test_data_directory.cc', @@ -2002,6 +2000,8 @@ 'disk_cache/flash/flash_cache_test_base.cc', 'dns/dns_test_util.cc', 'dns/dns_test_util.h', + 'dns/mock_host_resolver.cc', + 'dns/mock_host_resolver.h', 'proxy/mock_proxy_resolver.cc', 'proxy/mock_proxy_resolver.h', 'proxy/mock_proxy_script_fetcher.cc', diff --git a/net/proxy/proxy_resolver_perftest.cc b/net/proxy/proxy_resolver_perftest.cc index 762e053..aa25d51 100644 --- a/net/proxy/proxy_resolver_perftest.cc +++ b/net/proxy/proxy_resolver_perftest.cc @@ -8,8 +8,8 @@ #include "base/path_service.h" #include "base/perftimer.h" #include "base/string_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" +#include "net/dns/mock_host_resolver.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_v8.h" #include "net/test/test_server.h" diff --git a/net/proxy/proxy_resolver_v8_tracing.cc b/net/proxy/proxy_resolver_v8_tracing.cc index 198418f..a453768 100644 --- a/net/proxy/proxy_resolver_v8_tracing.cc +++ b/net/proxy/proxy_resolver_v8_tracing.cc @@ -14,9 +14,9 @@ #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "net/base/address_list.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" +#include "net/dns/host_resolver.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_error_observer.h" #include "net/proxy/proxy_resolver_v8.h" diff --git a/net/proxy/proxy_resolver_v8_tracing_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_unittest.cc index e0162d4..d3b15c3 100644 --- a/net/proxy/proxy_resolver_v8_tracing_unittest.cc +++ b/net/proxy/proxy_resolver_v8_tracing_unittest.cc @@ -16,11 +16,11 @@ #include "base/values.h" #include "googleurl/src/gurl.h" #include "net/base/host_cache.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_error_observer.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index e4ea2b9..19c6246 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc @@ -12,10 +12,10 @@ #include "base/utf_string_conversions.h" #include "net/base/load_flags.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_util.h" #include "net/base/test_completion_callback.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index c9418e8..293beec 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc @@ -6,8 +6,8 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "net/base/mock_cert_verifier.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" #include "net/http/http_network_transaction.h" diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 1cb3ff3..e33306a 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc @@ -11,9 +11,9 @@ #include "base/rand_util.h" #include "base/stl_util.h" #include "base/values.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/quic/crypto/quic_random.h" #include "net/quic/quic_client_session.h" #include "net/quic/quic_clock.h" diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 34b06b8..a34f80a 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc @@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "base/string_util.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_util.h" diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h index 7a274b7..9445845 100644 --- a/net/socket/client_socket_pool.h +++ b/net/socket/client_socket_pool.h @@ -10,13 +10,13 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" -#include "base/time.h" #include "base/template_util.h" +#include "base/time.h" #include "net/base/completion_callback.h" -#include "net/base/host_resolver.h" #include "net/base/load_states.h" #include "net/base/net_export.h" #include "net/base/request_priority.h" +#include "net/dns/host_resolver.h" namespace base { class DictionaryValue; diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h index 38810df..cf6a484 100644 --- a/net/socket/socks5_client_socket.h +++ b/net/socket/socks5_client_socket.h @@ -14,9 +14,9 @@ #include "googleurl/src/gurl.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" +#include "net/dns/host_resolver.h" #include "net/socket/stream_socket.h" namespace net { diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc index efdd129..9a55090 100644 --- a/net/socket/socks5_client_socket_unittest.cc +++ b/net/socket/socks5_client_socket_unittest.cc @@ -12,9 +12,9 @@ #include "net/base/address_list.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" +#include "net/dns/mock_host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/socket_test_util.h" #include "net/socket/tcp_client_socket.h" diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h index 6e74409..17d3ca6 100644 --- a/net/socket/socks_client_socket.h +++ b/net/socket/socks_client_socket.h @@ -13,10 +13,10 @@ #include "base/memory/scoped_ptr.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" #include "net/socket/stream_socket.h" namespace net { diff --git a/net/socket/socks_client_socket_pool.h b/net/socket/socks_client_socket_pool.h index 96c48426..3fb08eb 100644 --- a/net/socket/socks_client_socket_pool.h +++ b/net/socket/socks_client_socket_pool.h @@ -13,10 +13,10 @@ #include "base/memory/scoped_ptr.h" #include "base/time.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/socket/client_socket_pool.h" #include "net/socket/client_socket_pool_base.h" #include "net/socket/client_socket_pool_histograms.h" -#include "net/socket/client_socket_pool.h" namespace net { diff --git a/net/socket/socks_client_socket_pool_unittest.cc b/net/socket/socks_client_socket_pool_unittest.cc index ab559ca..1c0e5a6 100644 --- a/net/socket/socks_client_socket_pool_unittest.cc +++ b/net/socket/socks_client_socket_pool_unittest.cc @@ -9,9 +9,9 @@ #include "base/time.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_histograms.h" diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc index 2677b5b..cff9c26 100644 --- a/net/socket/socks_client_socket_unittest.cc +++ b/net/socket/socks_client_socket_unittest.cc @@ -7,12 +7,12 @@ #include "net/base/address_list.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" +#include "net/dns/mock_host_resolver.h" #include "net/socket/client_socket_factory.h" -#include "net/socket/tcp_client_socket.h" #include "net/socket/socket_test_util.h" +#include "net/socket/tcp_client_socket.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/net/socket/ssl_client_socket_openssl_unittest.cc b/net/socket/ssl_client_socket_openssl_unittest.cc index 85f5a0c..5b0bb2a 100644 --- a/net/socket/ssl_client_socket_openssl_unittest.cc +++ b/net/socket/ssl_client_socket_openssl_unittest.cc @@ -21,7 +21,6 @@ #include "crypto/openssl_util.h" #include "net/base/address_list.h" #include "net/base/cert_test_util.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/mock_cert_verifier.h" #include "net/base/net_errors.h" @@ -31,6 +30,7 @@ #include "net/base/test_completion_callback.h" #include "net/base/test_data_directory.h" #include "net/base/test_root_certs.h" +#include "net/dns/host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socket_test_util.h" diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h index a0a5d3b..e6e291e 100644 --- a/net/socket/ssl_client_socket_pool.h +++ b/net/socket/ssl_client_socket_pool.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" #include "net/http/http_response_info.h" #include "net/proxy/proxy_server.h" #include "net/socket/client_socket_pool.h" diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index 6e31442..4d52729 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -13,10 +13,10 @@ #include "net/base/cert_verifier.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_certificate_data.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 3163077..6507f0d 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc @@ -8,7 +8,6 @@ #include "base/memory/ref_counted.h" #include "net/base/address_list.h" #include "net/base/cert_test_util.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/mock_cert_verifier.h" #include "net/base/net_errors.h" @@ -17,6 +16,7 @@ #include "net/base/test_completion_callback.h" #include "net/base/test_data_directory.h" #include "net/base/test_root_certs.h" +#include "net/dns/host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socket_test_util.h" diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index 2a1053c..f0900b2 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h @@ -13,11 +13,11 @@ #include "base/time.h" #include "base/timer.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" -#include "net/base/single_request_host_resolver.h" +#include "net/dns/host_resolver.h" +#include "net/dns/single_request_host_resolver.h" +#include "net/socket/client_socket_pool.h" #include "net/socket/client_socket_pool_base.h" #include "net/socket/client_socket_pool_histograms.h" -#include "net/socket/client_socket_pool.h" namespace net { diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 45b5485..ffea811 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc @@ -15,10 +15,10 @@ #include "net/base/ip_endpoint.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_histograms.h" diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc index 73136ae..6bf9d28 100644 --- a/net/socket/transport_client_socket_unittest.cc +++ b/net/socket/transport_client_socket_unittest.cc @@ -9,13 +9,13 @@ #include "base/memory/scoped_ptr.h" #include "net/base/address_list.h" #include "net/base/io_buffer.h" -#include "net/base/mock_host_resolver.h" +#include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" -#include "net/base/net_errors.h" #include "net/base/tcp_listen_socket.h" #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" +#include "net/dns/mock_host_resolver.h" #include "net/socket/client_socket_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc index 8838bd3..0b1bc5c 100644 --- a/net/socket_stream/socket_stream.cc +++ b/net/socket_stream/socket_stream.cc @@ -20,10 +20,10 @@ #include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "net/base/auth.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" +#include "net/dns/host_resolver.h" #include "net/http/http_auth_controller.h" #include "net/http/http_network_session.h" #include "net/http/http_request_headers.h" diff --git a/net/socket_stream/socket_stream_unittest.cc b/net/socket_stream/socket_stream_unittest.cc index 8007767..ed3aa9b 100644 --- a/net/socket_stream/socket_stream_unittest.cc +++ b/net/socket_stream/socket_stream_unittest.cc @@ -12,10 +12,10 @@ #include "base/callback.h" #include "base/utf_string_conversions.h" #include "net/base/auth.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" #include "net/base/test_completion_callback.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_network_session.h" #include "net/proxy/proxy_service.h" #include "net/socket/socket_test_util.h" diff --git a/net/spdy/spdy_proxy_client_socket_spdy2_unittest.cc b/net/spdy/spdy_proxy_client_socket_spdy2_unittest.cc index b98c9df..d6117ab 100644 --- a/net/spdy/spdy_proxy_client_socket_spdy2_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_spdy2_unittest.cc @@ -11,22 +11,22 @@ #include "net/base/capturing_net_log.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" -#include "net/http/http_response_info.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" +#include "net/http/http_response_info.h" #include "net/socket/client_socket_factory.h" -#include "net/socket/tcp_client_socket.h" #include "net/socket/socket_test_util.h" +#include "net/socket/tcp_client_socket.h" #include "net/spdy/buffered_spdy_framer.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_protocol.h" #include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_test_util_common.h" #include "net/spdy/spdy_test_util_spdy2.h" -#include "testing/platform_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" using namespace net::test_spdy2; diff --git a/net/spdy/spdy_proxy_client_socket_spdy3_unittest.cc b/net/spdy/spdy_proxy_client_socket_spdy3_unittest.cc index 85db660..5dac149 100644 --- a/net/spdy/spdy_proxy_client_socket_spdy3_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_spdy3_unittest.cc @@ -11,22 +11,22 @@ #include "net/base/capturing_net_log.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" -#include "net/base/mock_host_resolver.h" #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" -#include "net/http/http_response_info.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" +#include "net/http/http_response_info.h" #include "net/socket/client_socket_factory.h" -#include "net/socket/tcp_client_socket.h" #include "net/socket/socket_test_util.h" +#include "net/socket/tcp_client_socket.h" #include "net/spdy/buffered_spdy_framer.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_protocol.h" #include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_test_util_common.h" #include "net/spdy/spdy_test_util_spdy3.h" -#include "testing/platform_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" using namespace net::test_spdy3; diff --git a/net/spdy/spdy_test_util_spdy2.h b/net/spdy/spdy_test_util_spdy2.h index 4d47b02..6054c38 100644 --- a/net/spdy/spdy_test_util_spdy2.h +++ b/net/spdy/spdy_test_util_spdy2.h @@ -10,8 +10,8 @@ #include "base/string_piece.h" #include "net/base/cert_verifier.h" #include "net/base/host_port_pair.h" -#include "net/base/mock_host_resolver.h" #include "net/base/request_priority.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" diff --git a/net/spdy/spdy_test_util_spdy3.h b/net/spdy/spdy_test_util_spdy3.h index dec5c05..27c8670 100644 --- a/net/spdy/spdy_test_util_spdy3.h +++ b/net/spdy/spdy_test_util_spdy3.h @@ -12,8 +12,8 @@ #include "crypto/ec_signature_creator.h" #include "net/base/cert_verifier.h" #include "net/base/host_port_pair.h" -#include "net/base/mock_host_resolver.h" #include "net/base/request_priority.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" diff --git a/net/test/base_test_server.cc b/net/test/base_test_server.cc index 39518e5..9500088e 100644 --- a/net/test/base_test_server.cc +++ b/net/test/base_test_server.cc @@ -16,12 +16,12 @@ #include "googleurl/src/gurl.h" #include "net/base/address_list.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_util.h" #include "net/base/test_completion_callback.h" #include "net/base/test_root_certs.h" +#include "net/dns/host_resolver.h" namespace net { diff --git a/net/test/net_test_suite.h b/net/test/net_test_suite.h index b2fed70..32e6b02b 100644 --- a/net/test/net_test_suite.h +++ b/net/test/net_test_suite.h @@ -8,7 +8,7 @@ #include "base/memory/ref_counted.h" #include "base/test/test_suite.h" #include "build/build_config.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" class MessageLoop; diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc index 7bb57a5..ef86826 100644 --- a/net/tools/fetch/fetch_client.cc +++ b/net/tools/fetch/fetch_client.cc @@ -15,10 +15,10 @@ #include "base/string_util.h" #include "net/base/cert_verifier.h" #include "net/base/completion_callback.h" -#include "net/base/host_resolver.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" +#include "net/dns/host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc index 55a8938..a818f01 100644 --- a/net/tools/gdig/gdig.cc +++ b/net/tools/gdig/gdig.cc @@ -19,7 +19,6 @@ #include "base/time.h" #include "net/base/address_list.h" #include "net/base/host_cache.h" -#include "net/base/host_resolver_impl.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" @@ -27,6 +26,7 @@ #include "net/dns/dns_client.h" #include "net/dns/dns_config_service.h" #include "net/dns/dns_protocol.h" +#include "net/dns/host_resolver_impl.h" #include "net/tools/gdig/file_net_log.h" #if defined(OS_MACOSX) diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index 2bfe850..e860feb 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc @@ -15,8 +15,8 @@ #include "base/threading/thread.h" #include "build/build_config.h" #include "crypto/nss_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/network_change_notifier.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" #include "net/test/test_server.h" #include "net/url_request/url_fetcher_delegate.h" diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index e88750b..d69d3e1 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc @@ -8,8 +8,8 @@ #include "base/debug/alias.h" #include "base/debug/stack_trace.h" #include "base/string_util.h" -#include "net/base/host_resolver.h" #include "net/cookies/cookie_store.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_transaction_factory.h" #include "net/http/http_transaction_factory.h" #include "net/url_request/http_user_agent_settings.h" diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 498e0ca..a84bc71 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc @@ -13,10 +13,10 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" #include "net/base/net_errors.h" #include "net/base/network_delegate.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_cache.h" diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc index e201b8e..ae4140f 100644 --- a/net/url_request/url_request_context_storage.cc +++ b/net/url_request/url_request_context_storage.cc @@ -6,10 +6,10 @@ #include "base/logging.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" #include "net/base/net_log.h" #include "net/base/network_delegate.h" #include "net/cookies/cookie_store.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_transaction_factory.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_server_properties.h" diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index e5c0051..5c72530 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -11,7 +11,7 @@ #include "base/threading/worker_pool.h" #include "net/base/cert_verifier.h" #include "net/base/host_port_pair.h" -#include "net/base/mock_host_resolver.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" #include "net/ssl/default_server_bound_cert_store.h" diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 32b99ac..ef98a65 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -33,7 +33,6 @@ #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_log_unittest.h" @@ -47,6 +46,7 @@ #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store_test_helpers.h" #include "net/disk_cache/disk_cache.h" +#include "net/dns/mock_host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" diff --git a/net/websockets/websocket_job_spdy2_unittest.cc b/net/websockets/websocket_job_spdy2_unittest.cc index 0dde5231..5c46f57 100644 --- a/net/websockets/websocket_job_spdy2_unittest.cc +++ b/net/websockets/websocket_job_spdy2_unittest.cc @@ -15,11 +15,11 @@ #include "base/strings/string_split.h" #include "googleurl/src/gurl.h" #include "net/base/completion_callback.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_store_test_helpers.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_transaction_factory.h" #include "net/http/transport_security_state.h" #include "net/proxy/proxy_service.h" diff --git a/net/websockets/websocket_job_spdy3_unittest.cc b/net/websockets/websocket_job_spdy3_unittest.cc index 5877e94..1cf7573 100644 --- a/net/websockets/websocket_job_spdy3_unittest.cc +++ b/net/websockets/websocket_job_spdy3_unittest.cc @@ -15,11 +15,11 @@ #include "base/strings/string_split.h" #include "googleurl/src/gurl.h" #include "net/base/completion_callback.h" -#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_store_test_helpers.h" +#include "net/dns/mock_host_resolver.h" #include "net/http/http_transaction_factory.h" #include "net/http/transport_security_state.h" #include "net/proxy/proxy_service.h" diff --git a/remoting/host/DEPS b/remoting/host/DEPS index 2f1aa54..4bca7ec 100644 --- a/remoting/host/DEPS +++ b/remoting/host/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+media/video/capture/screen", "+net/base", + "+net/dns", "+net/ftp", "+net/http", "+net/proxy", diff --git a/remoting/host/url_request_context.cc b/remoting/host/url_request_context.cc index aceccdb..26f7fdc 100644 --- a/remoting/host/url_request_context.cc +++ b/remoting/host/url_request_context.cc @@ -6,7 +6,7 @@ #include "base/message_loop_proxy.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" +#include "net/dns/host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" diff --git a/sync/internal_api/http_bridge.cc b/sync/internal_api/http_bridge.cc index d163be5..df864bf 100644 --- a/sync/internal_api/http_bridge.cc +++ b/sync/internal_api/http_bridge.cc @@ -7,10 +7,10 @@ #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/string_number_conversions.h" -#include "net/base/host_resolver.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_response_headers.h" diff --git a/sync/tools/sync_client.cc b/sync/tools/sync_client.cc index c773168..5fb0a0c 100644 --- a/sync/tools/sync_client.cc +++ b/sync/tools/sync_client.cc @@ -22,8 +22,8 @@ #include "jingle/notifier/base/notification_method.h" #include "jingle/notifier/base/notifier_options.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/network_change_notifier.h" +#include "net/dns/host_resolver.h" #include "net/http/transport_security_state.h" #include "net/url_request/url_request_test_util.h" #include "sync/internal_api/public/base/model_type.h" diff --git a/sync/tools/sync_listen_notifications.cc b/sync/tools/sync_listen_notifications.cc index c863df3..834b040 100644 --- a/sync/tools/sync_listen_notifications.cc +++ b/sync/tools/sync_listen_notifications.cc @@ -17,8 +17,8 @@ #include "jingle/notifier/base/notification_method.h" #include "jingle/notifier/base/notifier_options.h" #include "net/base/host_port_pair.h" -#include "net/base/host_resolver.h" #include "net/base/network_change_notifier.h" +#include "net/dns/host_resolver.h" #include "net/http/transport_security_state.h" #include "net/url_request/url_request_test_util.h" #include "sync/internal_api/public/base/model_type.h" diff --git a/webkit/DEPS b/webkit/DEPS index b760178..f5ae179 100644 --- a/webkit/DEPS +++ b/webkit/DEPS @@ -40,6 +40,7 @@ include_rules = [ "+crypto", "+net/base", "+net/cookies", + "+net/dns", "+net/ftp", "+net/http", "+net/proxy", diff --git a/webkit/tools/test_shell/test_shell_request_context.cc b/webkit/tools/test_shell/test_shell_request_context.cc index bfd2eb4d..5febc82 100644 --- a/webkit/tools/test_shell/test_shell_request_context.cc +++ b/webkit/tools/test_shell/test_shell_request_context.cc @@ -11,8 +11,8 @@ #include "base/thread_task_runner_handle.h" #include "base/threading/worker_pool.h" #include "net/base/cert_verifier.h" -#include "net/base/host_resolver.h" #include "net/cookies/cookie_monster.h" +#include "net/dns/host_resolver.h" #include "net/ftp/ftp_network_layer.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_session.h" -- cgit v1.1