AU: Proxy Resolver classes
A collection of classes (abstract ProxyResolver interface and two
concrete implementations). The abstraction is one that should suit us
moving forward: a string URL is provided and a collection of proxy
servers is returned. One implementation always returns [no
proxy]. Another returns [manual settings from chrome, if applicable,
..., no proxy].
A future concrete implementation will consult Chrome via DBus with the
URL in question, however this is delayed until Chrome exposes such an
API.
As a result of this API missing from Chrome, this CL only resolves
proxies for a URL with manually input proxy settings.
Future CLs will integrate this into the rest of the update system.
BUG=3167
TEST=unit tests, (with future CLs) working proxy support on device
Review URL: http://codereview.chromium.org/5151005
Change-Id: If9dc6d09da681bca6f6ae74c896ba946ab81cb4d
diff --git a/SConstruct b/SConstruct
index f772882..97cc6e3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -236,6 +236,7 @@
buffered_file_writer.cc
bzip.cc
bzip_extent_writer.cc
+ chrome_proxy_resolver.cc
cycle_breaker.cc
dbus_service.cc
decompressing_file_writer.cc
@@ -261,6 +262,7 @@
payload_signer.cc
postinstall_runner_action.cc
prefs.cc
+ proxy_resolver.cc
simple_key_value_store.cc
split_file_writer.cc
subprocess.cc
@@ -278,6 +280,7 @@
action_processor_unittest.cc
buffered_file_writer_unittest.cc
bzip_extent_writer_unittest.cc
+ chrome_proxy_resolver_unittest.cc
cycle_breaker_unittest.cc
decompressing_file_writer_unittest.cc
delta_diff_generator_unittest.cc
diff --git a/chrome_proxy_resolver.cc b/chrome_proxy_resolver.cc
new file mode 100644
index 0000000..eaa213a
--- /dev/null
+++ b/chrome_proxy_resolver.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2010 The Chromium OS 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 "update_engine/chrome_proxy_resolver.h"
+
+#include <base/json/json_reader.h>
+#include <base/scoped_ptr.h>
+#include <base/values.h>
+
+#include "update_engine/utils.h"
+
+using std::string;
+using std::vector;
+
+namespace chromeos_update_engine {
+
+const char kSessionManagerService[] = "org.chromium.SessionManager";
+const char kSessionManagerPath[] = "/org/chromium/SessionManager";
+const char kSessionManagerInterface[] = "org.chromium.SessionManagerInterface";
+const char kSessionManagerRetrievePropertyMethod[] =
+ "RetrieveProperty";
+const char kSessionManagerProxySettingsKey[] = "cros.proxy.everywhere";
+
+bool ChromeProxyResolver::GetProxiesForUrl(
+ const std::string& url,
+ std::vector<std::string>* out_proxies) {
+ // First, query dbus for the currently stored settings
+ DBusGProxy* proxy = DbusProxy();
+ TEST_AND_RETURN_FALSE(proxy);
+ string json_settings;
+ TEST_AND_RETURN_FALSE(GetJsonProxySettings(proxy, &json_settings));
+ LOG(INFO) << "got settings:" << json_settings;
+ TEST_AND_RETURN_FALSE(
+ GetProxiesForUrlWithSettings(url, json_settings, out_proxies));
+ return true;
+}
+
+bool ChromeProxyResolver::GetJsonProxySettings(DBusGProxy* proxy,
+ std::string* out_json) {
+ gchar* value = NULL;
+ GArray* sig = NULL;
+ GError* error = NULL;
+ TEST_AND_RETURN_FALSE(
+ dbus_->ProxyCall(proxy,
+ kSessionManagerRetrievePropertyMethod,
+ &error,
+ G_TYPE_STRING, kSessionManagerProxySettingsKey,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &value,
+ DBUS_TYPE_G_UCHAR_ARRAY, &sig,
+ G_TYPE_INVALID));
+ g_array_free(sig, false);
+ out_json->assign(value);
+ g_free(value);
+ return true;
+}
+
+DBusGProxy* ChromeProxyResolver::DbusProxy() {
+ GError* error = NULL;
+ DBusGConnection* bus = dbus_->BusGet(DBUS_BUS_SYSTEM, &error);
+ TEST_AND_RETURN_FALSE(bus);
+ DBusGProxy* proxy = dbus_->ProxyNewForNameOwner(bus,
+ kSessionManagerService,
+ kSessionManagerPath,
+ kSessionManagerInterface,
+ &error);
+ if (!proxy) {
+ LOG(ERROR) << "Error getting FlimFlam proxy: "
+ << utils::GetGErrorMessage(error);
+ }
+ return proxy;
+}
+
+namespace {
+enum ProxyMode {
+ kProxyModeDirect = 0,
+ kProxyModeAutoDetect,
+ kProxyModePACScript,
+ kProxyModeSingle,
+ kProxyModeProxyPerScheme
+};
+} // namespace {}
+
+bool ChromeProxyResolver::GetProxiesForUrlWithSettings(
+ const string& url,
+ const string& json_settings,
+ std::vector<std::string>* out_proxies) {
+ base::JSONReader parser;
+
+ scoped_ptr<Value> root(
+ parser.JsonToValue(json_settings,
+ true, // check root is obj/arr
+ false)); // false = disallow trailing comma
+ if (!root.get()) {
+ LOG(ERROR) << "Unable to parse \"" << json_settings << "\": "
+ << parser.GetErrorMessage();
+ return false;
+ }
+
+ TEST_AND_RETURN_FALSE(root->IsType(Value::TYPE_DICTIONARY));
+
+ DictionaryValue* root_dict = dynamic_cast<DictionaryValue*>(root.get());
+ TEST_AND_RETURN_FALSE(root_dict);
+ int mode = -1;
+ TEST_AND_RETURN_FALSE(root_dict->GetInteger("mode", &mode));
+
+ LOG(INFO) << "proxy mode: " << mode;
+ if (mode != kProxyModeSingle &&
+ mode != kProxyModeProxyPerScheme) {
+ LOG(INFO) << "unsupported proxy scheme";
+ out_proxies->clear();
+ out_proxies->push_back(kNoProxy);
+ return true;
+ }
+ if (mode == kProxyModeSingle) {
+ LOG(INFO) << "single proxy mode";
+ string proxy_string;
+ TEST_AND_RETURN_FALSE(root_dict->GetString("single.server", &proxy_string));
+ if (proxy_string.find("://") == string::npos) {
+ // missing protocol, assume http.
+ proxy_string = string("http://") + proxy_string;
+ }
+ out_proxies->clear();
+ out_proxies->push_back(proxy_string);
+ LOG(INFO) << "single proxy: " << (*out_proxies)[0];
+ out_proxies->push_back(kNoProxy);
+ return true;
+ }
+ // Proxy per scheme mode.
+ LOG(INFO) << "proxy per scheme mode";
+
+ // Find which scheme we are
+ bool url_is_http = utils::StringHasPrefix(url, "http://");
+ if (!url_is_http)
+ TEST_AND_RETURN_FALSE(utils::StringHasPrefix(url, "https://"));
+
+ // Using "proto_*" variables to refer to http or https
+ const string proto_path = url_is_http ? "http.server" : "https.server";
+ const string socks_path = "socks.server";
+
+ out_proxies->clear();
+
+ string proto_server, socks_server;
+ if (root_dict->GetString(proto_path, &proto_server)) {
+ if (proto_server.find("://") == string::npos) {
+ // missing protocol, assume http.
+ proto_server = string("http://") + proto_server;
+ }
+ out_proxies->push_back(proto_server);
+ LOG(INFO) << "got http/https server: " << proto_server;
+ }
+ if (root_dict->GetString(socks_path, &socks_server)) {
+ out_proxies->push_back(socks_server);
+ LOG(INFO) << "got socks server: " << proto_server;
+ }
+ out_proxies->push_back(kNoProxy);
+ return true;
+}
+
+bool ChromeProxyResolver::GetProxyType(const std::string& proxy,
+ curl_proxytype* out_type) {
+ if (utils::StringHasPrefix(proxy, "socks5://") ||
+ utils::StringHasPrefix(proxy, "socks://")) {
+ *out_type = CURLPROXY_SOCKS5_HOSTNAME;
+ return true;
+ }
+ if (utils::StringHasPrefix(proxy, "socks4://")) {
+ *out_type = CURLPROXY_SOCKS4A;
+ return true;
+ }
+ if (utils::StringHasPrefix(proxy, "http://") ||
+ utils::StringHasPrefix(proxy, "https://")) {
+ *out_type = CURLPROXY_HTTP;
+ return true;
+ }
+ if (utils::StringHasPrefix(proxy, kNoProxy)) {
+ // known failure case. don't log.
+ return false;
+ }
+ LOG(INFO) << "Unknown proxy type: " << proxy;
+ return false;
+}
+
+} // namespace chromeos_update_engine
diff --git a/chrome_proxy_resolver.h b/chrome_proxy_resolver.h
new file mode 100644
index 0000000..796f8fb
--- /dev/null
+++ b/chrome_proxy_resolver.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2010 The Chromium OS 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 CHROMEOS_PLATFORM_UPDATE_ENGINE_CHROME_PROXY_RESOLVER_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_CHROME_PROXY_RESOLVER_H__
+
+#include <string>
+#include <vector>
+
+#include <curl/curl.h>
+#include <gtest/gtest_prod.h> // for FRIEND_TEST
+
+#include "update_engine/dbus_interface.h"
+#include "update_engine/proxy_resolver.h"
+
+namespace chromeos_update_engine {
+
+extern const char kSessionManagerService[];
+extern const char kSessionManagerPath[];
+extern const char kSessionManagerInterface[];
+extern const char kSessionManagerRetrievePropertyMethod[];
+extern const char kSessionManagerProxySettingsKey[];
+
+// Class to resolve proxy for a url based on Chrome's proxy settings.
+
+// Currently only supports manual settings, not PAC files or autodetected
+// settings.
+
+class ChromeProxyResolver : public ProxyResolver {
+ public:
+ explicit ChromeProxyResolver(DbusGlibInterface* dbus) : dbus_(dbus) {}
+ virtual ~ChromeProxyResolver() {}
+
+ virtual bool GetProxiesForUrl(const std::string& url,
+ std::vector<std::string>* out_proxies);
+
+ // Get the curl proxy type for a given proxy url. Returns true on success.
+ // Note: if proxy is kNoProxy, this will return false.
+ static bool GetProxyType(const std::string& proxy,
+ curl_proxytype* out_type);
+
+ private:
+ FRIEND_TEST(ChromeProxyResolverTest, GetProxiesForUrlWithSettingsTest);
+
+ // Fetches a dbus proxy to session manager. Returns NULL on failure.
+ DBusGProxy* DbusProxy();
+
+ // Fetches the json-encoded proxy settings string from the session manager.
+ bool GetJsonProxySettings(DBusGProxy* proxy, std::string* out_json);
+
+ // Given a |url| and the json encoded settings |json_settings|,
+ // returns the proper proxy servers in |out_proxies|. Returns true on
+ // success.
+ bool GetProxiesForUrlWithSettings(const std::string& url,
+ const std::string& json_settings,
+ std::vector<std::string>* out_proxies);
+
+ DbusGlibInterface* dbus_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeProxyResolver);
+};
+
+} // namespace chromeos_update_engine
+
+#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_CHROME_PROXY_RESOLVER_H__
diff --git a/chrome_proxy_resolver_unittest.cc b/chrome_proxy_resolver_unittest.cc
new file mode 100644
index 0000000..66b2401
--- /dev/null
+++ b/chrome_proxy_resolver_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright (c) 2009 The Chromium OS 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 <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "update_engine/chrome_proxy_resolver.h"
+#include "update_engine/mock_dbus_interface.h"
+
+using std::string;
+using std::vector;
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+using ::testing::StrEq;
+
+namespace chromeos_update_engine {
+
+class ChromeProxyResolverTest : public ::testing::Test { };
+
+TEST(ChromeProxyResolverTest, GetProxiesForUrlWithSettingsTest) {
+ const string kSingle =
+ "{\"mode\":3,\"single\":{\"server\":\"192.168.42.86:80\",\"src\":0}}";
+ const string kSocks =
+ "{\"mode\":4,\"socks\":{\"server\":\"socks5://192.168.42.83:5555\","
+ "\"src\":0}}";
+ const string kAll =
+ "{\"http\":{\"server\":\"http_proxy:11\",\"src\":0},"
+ "\"https\":{\"server\":\"https://https_proxy:22\",\"src\":0},"
+ "\"mode\":4,"
+ "\"socks\":{\"server\":\"socks5://socks:55\",\"src\":0}}";
+ const string kHttpHttps =
+ "{\"http\":{\"server\":\"http_proxy:11\",\"src\":0},"
+ "\"https\":{\"server\":\"https://https_proxy:22\",\"src\":0},"
+ "\"mode\":4}";
+
+ ChromeProxyResolver resolver(NULL);
+ vector<string> out;
+ string urls[] = {"http://foo.com/update", "https://bar.com/foo.gz"};
+ string multi_settings[] = {kAll, kHttpHttps};
+ for (size_t i = 0; i < arraysize(urls); i++) {
+ const string& url = urls[i];
+ LOG(INFO) << "url: " << url;
+ EXPECT_TRUE(resolver.GetProxiesForUrlWithSettings(url, kSingle, &out));
+ EXPECT_EQ(2, out.size());
+ EXPECT_EQ("http://192.168.42.86:80", out[0]);
+ EXPECT_EQ(kNoProxy, out[1]);
+
+ EXPECT_TRUE(resolver.GetProxiesForUrlWithSettings(url, kSocks, &out));
+ EXPECT_EQ(2, out.size());
+ EXPECT_EQ("socks5://192.168.42.83:5555", out[0]);
+ EXPECT_EQ(kNoProxy, out[1]);
+
+ for (size_t j = 0; j < arraysize(multi_settings); j++) {
+ const string& settings = multi_settings[j];
+ EXPECT_TRUE(resolver.GetProxiesForUrlWithSettings(url, settings, &out));
+ EXPECT_EQ(j == 0 ? 3 : 2, out.size());
+ if (i == 0)
+ EXPECT_EQ("http://http_proxy:11", out[0]);
+ else
+ EXPECT_EQ("https://https_proxy:22", out[0]);
+ if (j == 0)
+ EXPECT_EQ("socks5://socks:55", out[1]);
+ EXPECT_EQ(kNoProxy, out.back());
+ }
+ }
+
+ // Bad JSON
+ EXPECT_FALSE(resolver.GetProxiesForUrlWithSettings("http://foo.com",
+ "}",
+ &out));
+
+ // Bad proxy scheme
+ EXPECT_TRUE(resolver.GetProxiesForUrlWithSettings("http://foo.com",
+ "{\"mode\":1}",
+ &out));
+ EXPECT_EQ(1, out.size());
+ EXPECT_EQ(kNoProxy, out[0]);
+}
+
+TEST(ChromeProxyResolverTest, DbusInterfaceTest) {
+ long number = 1;
+ DBusGConnection* kMockSystemBus =
+ reinterpret_cast<DBusGConnection*>(number++);
+ DBusGProxy* kMockSessionManagerProxy =
+ reinterpret_cast<DBusGProxy*>(number++);
+
+ const char settings[] =
+ "{\"mode\":4,\"socks\":{\"server\":\"socks5://192.168.52.83:5555\","
+ "\"src\":0}}";
+
+ MockDbusGlib dbus_iface;
+ ChromeProxyResolver resolver(&dbus_iface);
+
+ GArray* ret_array = g_array_new(FALSE, FALSE, 1);
+
+ EXPECT_CALL(dbus_iface, BusGet(DBUS_BUS_SYSTEM, _))
+ .Times(1)
+ .WillRepeatedly(Return(kMockSystemBus));
+ EXPECT_CALL(dbus_iface,
+ ProxyNewForNameOwner(kMockSystemBus,
+ StrEq(kSessionManagerService),
+ StrEq(kSessionManagerPath),
+ StrEq(kSessionManagerInterface),
+ _))
+ .WillOnce(Return(kMockSessionManagerProxy));
+ EXPECT_CALL(dbus_iface, ProxyCall(
+ kMockSessionManagerProxy,
+ StrEq(kSessionManagerRetrievePropertyMethod),
+ _,
+ G_TYPE_STRING, StrEq(kSessionManagerProxySettingsKey),
+ G_TYPE_INVALID,
+ G_TYPE_STRING, _,
+ DBUS_TYPE_G_UCHAR_ARRAY, _))
+ .WillOnce(DoAll(SetArgumentPointee<7>(strdup(settings)),
+ SetArgumentPointee<9>(ret_array),
+ Return(TRUE)));
+
+ vector<string> proxies;
+ EXPECT_TRUE(resolver.GetProxiesForUrl("http://user:pass@foo.com:22",
+ &proxies));
+ EXPECT_EQ(2, proxies.size());
+ EXPECT_EQ("socks5://192.168.52.83:5555", proxies[0]);
+ EXPECT_EQ(kNoProxy, proxies[1]);
+}
+
+TEST(ChromeProxyResolverTest, GetProxyTypeTest) {
+ curl_proxytype type;
+ EXPECT_TRUE(ChromeProxyResolver::GetProxyType("socks://f.ru", &type));
+ EXPECT_EQ(CURLPROXY_SOCKS5_HOSTNAME, type);
+ EXPECT_TRUE(ChromeProxyResolver::GetProxyType("socks5://f.ru:9", &type));
+ EXPECT_EQ(CURLPROXY_SOCKS5_HOSTNAME, type);
+ EXPECT_TRUE(ChromeProxyResolver::GetProxyType("socks4://f.ru:9", &type));
+ EXPECT_EQ(CURLPROXY_SOCKS4A, type);
+ EXPECT_TRUE(ChromeProxyResolver::GetProxyType("http://f.no:88", &type));
+ EXPECT_EQ(CURLPROXY_HTTP, type);
+ EXPECT_TRUE(ChromeProxyResolver::GetProxyType("https://f.no:88", &type));
+ EXPECT_EQ(CURLPROXY_HTTP, type);
+ EXPECT_FALSE(ChromeProxyResolver::GetProxyType(kNoProxy, &type));
+ EXPECT_FALSE(ChromeProxyResolver::GetProxyType("foo://", &type));
+ EXPECT_FALSE(ChromeProxyResolver::GetProxyType("missing.com:8", &type));
+}
+
+} // namespace chromeos_update_engine
diff --git a/dbus_interface.h b/dbus_interface.h
index 1b5c953..de09fff 100644
--- a/dbus_interface.h
+++ b/dbus_interface.h
@@ -7,6 +7,7 @@
// This class interfaces with DBus. The interface allows it to be mocked.
+#include <base/logging.h>
#include <dbus/dbus-glib.h>
namespace chromeos_update_engine {
@@ -25,7 +26,7 @@
// wraps dbus_g_bus_get
virtual DBusGConnection* BusGet(DBusBusType type, GError** error) = 0;
-
+
// wraps dbus_g_proxy_call
virtual gboolean ProxyCall(DBusGProxy* proxy,
const char* method,
@@ -34,6 +35,15 @@
GType var_arg1,
GHashTable** var_arg2,
GType var_arg3) = 0;
+
+ virtual gboolean ProxyCall(DBusGProxy* proxy,
+ const char* method,
+ GError** error,
+ GType var_arg1, const char* var_arg2,
+ GType var_arg3,
+ GType var_arg4, gchar** var_arg5,
+ GType var_arg6, GArray** var_arg7,
+ GType var_arg8) = 0;
};
class ConcreteDbusGlib : public DbusGlibInterface {
@@ -67,6 +77,19 @@
return dbus_g_proxy_call(
proxy, method, error, first_arg_type, var_arg1, var_arg2, var_arg3);
}
+
+ virtual gboolean ProxyCall(DBusGProxy* proxy,
+ const char* method,
+ GError** error,
+ GType var_arg1, const char* var_arg2,
+ GType var_arg3,
+ GType var_arg4, gchar** var_arg5,
+ GType var_arg6, GArray** var_arg7,
+ GType var_arg8) {
+ return dbus_g_proxy_call(
+ proxy, method, error, var_arg1, var_arg2, var_arg3,
+ var_arg4, var_arg5, var_arg6, var_arg7, var_arg8);
+ }
};
} // namespace chromeos_update_engine
diff --git a/mock_dbus_interface.h b/mock_dbus_interface.h
index bf0d609..c817109 100644
--- a/mock_dbus_interface.h
+++ b/mock_dbus_interface.h
@@ -30,6 +30,34 @@
GType var_arg1,
GHashTable** var_arg2,
GType var_arg3));
+ MOCK_METHOD10(ProxyCall, gboolean(DBusGProxy* proxy,
+ const char* method,
+ GError** error,
+ GType var_arg1, const char* var_arg2,
+ GType var_arg3,
+ GType var_arg4, gchar** var_arg5,
+ GType var_arg6, GArray** var_arg7));
+
+ // Since gmock only supports mocking functions up to 10 args, we
+ // take the 11-arg function we'd like to mock, drop the last arg
+ // and call the 10-arg version. Dropping the last arg isn't ideal,
+ // but this is a lot better than nothing.
+ gboolean ProxyCall(DBusGProxy* proxy,
+ const char* method,
+ GError** error,
+ GType var_arg1, const char* var_arg2,
+ GType var_arg3,
+ GType var_arg4, gchar** var_arg5,
+ GType var_arg6, GArray** var_arg7,
+ GType var_arg8) {
+ return ProxyCall(proxy,
+ method,
+ error,
+ var_arg1, var_arg2,
+ var_arg3,
+ var_arg4, var_arg5,
+ var_arg6, var_arg7);
+ }
};
} // namespace chromeos_update_engine
diff --git a/proxy_resolver.cc b/proxy_resolver.cc
new file mode 100644
index 0000000..6b3bd93
--- /dev/null
+++ b/proxy_resolver.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 The Chromium OS 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 "update_engine/proxy_resolver.h"
+
+using std::string;
+using std::vector;
+
+namespace chromeos_update_engine {
+
+const char kNoProxy[] = "direct://";
+
+bool DirectProxyResolver::GetProxiesForUrl(const string& url,
+ vector<string>* out_proxies) {
+ out_proxies->clear();
+ out_proxies->push_back(kNoProxy);
+ return true;
+}
+
+} // namespace chromeos_update_engine
diff --git a/proxy_resolver.h b/proxy_resolver.h
new file mode 100644
index 0000000..5d9064c
--- /dev/null
+++ b/proxy_resolver.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 The Chromium OS 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 CHROMEOS_PLATFORM_UPDATE_ENGINE_PROXY_RESOLVER_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_PROXY_RESOLVER_H__
+
+#include <base/logging.h>
+
+#include <string>
+#include <vector>
+
+namespace chromeos_update_engine {
+
+extern const char kNoProxy[];
+
+class ProxyResolver {
+ public:
+ ProxyResolver() {}
+ virtual ~ProxyResolver() {}
+
+ // Stores a list of proxies for a given |url| in |out_proxy|.
+ // Returns true on success. The resultant proxy will be in one of the
+ // following forms:
+ // http://<host>[:<port>] - HTTP proxy
+ // socks{4,5}://<host>[:<port>] - SOCKS4/5 proxy
+ // kNoProxy - no proxy
+ virtual bool GetProxiesForUrl(const std::string& url,
+ std::vector<std::string>* out_proxies) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProxyResolver);
+};
+
+// Always says to not use a proxy
+class DirectProxyResolver : public ProxyResolver {
+ public:
+ virtual bool GetProxiesForUrl(const std::string& url,
+ std::vector<std::string>* out_proxies);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DirectProxyResolver);
+};
+
+} // namespace chromeos_update_engine
+
+#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PROXY_RESOLVER_H__