Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2878)

Unified Diff: chrome_browser_proxy_resolver.cc

Issue 6594025: AU: Full proxy support (Closed) Base URL: http://git.chromium.org/git/update_engine.git@master
Patch Set: fixes for review Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome_browser_proxy_resolver.h ('k') | chrome_browser_proxy_resolver_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome_browser_proxy_resolver.cc
diff --git a/chrome_browser_proxy_resolver.cc b/chrome_browser_proxy_resolver.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a481f4fbb0d1d9ef68109ab0333320d62d8db126
--- /dev/null
+++ b/chrome_browser_proxy_resolver.cc
@@ -0,0 +1,268 @@
+// Copyright (c) 2011 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_browser_proxy_resolver.h"
+
+#include <map>
+#include <string>
+
+#include <base/string_tokenizer.h>
+#include <base/string_util.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <google/protobuf/stubs/common.h>
+
+#include "update_engine/dbus_constants.h"
+#include "update_engine/utils.h"
+
+namespace chromeos_update_engine {
+
+using google::protobuf::Closure;
+using google::protobuf::NewCallback;
+using std::deque;
+using std::make_pair;
+using std::multimap;
+using std::pair;
+using std::string;
+
+#define LIB_CROS_PROXY_RESOLVE_NAME "ProxyResolved"
+#define LIB_CROS_PROXY_RESOLVE_SIGNAL_INTERFACE \
+ "org.chromium.UpdateEngineLibcrosProxyResolvedInterface"
+const char kLibCrosServiceName[] = "org.chromium.LibCrosService";
+const char kLibCrosServicePath[] = "/org/chromium/LibCrosService";
+const char kLibCrosServiceInterface[] = "org.chromium.LibCrosServiceInterface";
+const char kLibCrosServiceResolveNetworkProxyMethodName[] =
+ "ResolveNetworkProxy";
+const char kLibCrosProxyResolveName[] = LIB_CROS_PROXY_RESOLVE_NAME;
+const char kLibCrosProxyResolveSignalInterface[] =
+ LIB_CROS_PROXY_RESOLVE_SIGNAL_INTERFACE;
+const char kLibCrosProxyResolveSignalFilter[] = "type='signal', "
+ "interface='" LIB_CROS_PROXY_RESOLVE_SIGNAL_INTERFACE "', "
+ "path='/', "
+ "member='" LIB_CROS_PROXY_RESOLVE_NAME "'";
+#undef LIB_CROS_PROXY_RESOLVE_SIGNAL_INTERFACE
+#undef LIB_CROS_PROXY_RESOLVE_NAME
+
+namespace {
+const int kTimeout = 5; // seconds
+
+DBusGProxy* GetProxy(DbusGlibInterface* dbus) {
+ GError* error = NULL;
+
+ DBusGConnection* bus = dbus->BusGet(DBUS_BUS_SYSTEM, &error);
+ if (!bus) {
+ LOG(ERROR) << "Failed to get bus";
+ return NULL;
+ }
+ DBusGProxy* proxy = dbus->ProxyNewForNameOwner(bus,
+ kLibCrosServiceName,
+ kLibCrosServicePath,
+ kLibCrosServiceInterface,
+ &error);
+ if (!proxy) {
+ LOG(ERROR) << "Error getting dbus proxy for "
+ << kLibCrosServiceName << ": " << utils::GetGErrorMessage(error);
+ return NULL;
+ }
+ return proxy;
+}
+
+} // namespace {}
+
+ChromeBrowserProxyResolver::ChromeBrowserProxyResolver(DbusGlibInterface* dbus)
+ : dbus_(dbus), proxy_(NULL), timeout_(kTimeout) {}
+
+bool ChromeBrowserProxyResolver::Init() {
+ // Set up signal handler. Code lifted from libcros
+ if (proxy_) {
+ // Already initialized
+ return true;
+ }
+ GError* gerror = NULL;
+ DBusGConnection* gbus = dbus_->BusGet(DBUS_BUS_SYSTEM, &gerror);
+ TEST_AND_RETURN_FALSE(gbus);
+ DBusConnection* connection = dbus_->ConnectionGetConnection(gbus);
+ TEST_AND_RETURN_FALSE(connection);
+ DBusError error;
+ dbus_error_init(&error);
+ dbus_->DbusBusAddMatch(connection, kLibCrosProxyResolveSignalFilter, &error);
+ TEST_AND_RETURN_FALSE(!dbus_error_is_set(&error));
+ TEST_AND_RETURN_FALSE(dbus_->DbusConnectionAddFilter(
+ connection,
+ &ChromeBrowserProxyResolver::StaticFilterMessage,
+ this,
+ NULL));
+
+ proxy_ = GetProxy(dbus_);
+ if (!proxy_) {
+ dbus_->DbusConnectionRemoveFilter(
+ connection,
+ &ChromeBrowserProxyResolver::StaticFilterMessage,
+ this);
+ }
+ TEST_AND_RETURN_FALSE(proxy_); // For the error log
+ return true;
+}
+
+ChromeBrowserProxyResolver::~ChromeBrowserProxyResolver() {
+ if (proxy_) {
+ GError* gerror = NULL;
+ DBusGConnection* gbus = dbus_->BusGet(DBUS_BUS_SYSTEM, &gerror);
+ TEST_AND_RETURN(gbus);
+ DBusConnection* connection = dbus_->ConnectionGetConnection(gbus);
+ dbus_->DbusConnectionRemoveFilter(
+ connection,
+ &ChromeBrowserProxyResolver::StaticFilterMessage,
+ this);
+ }
+ // Kill outstanding timers
+ for (TimeoutsMap::iterator it = timers_.begin(), e = timers_.end(); it != e;
+ ++it) {
+ g_source_destroy(it->second);
+ it->second = NULL;
+ }
+}
+
+bool ChromeBrowserProxyResolver::GetProxiesForUrl(const string& url,
+ ProxiesResolvedFn callback,
+ void* data) {
+ GError* error = NULL;
+ TEST_AND_RETURN_FALSE(proxy_);
+ if (!dbus_->ProxyCall(
+ proxy_,
+ kLibCrosServiceResolveNetworkProxyMethodName,
+ &error,
+ G_TYPE_STRING, url.c_str(),
+ G_TYPE_STRING, kLibCrosProxyResolveSignalInterface,
+ G_TYPE_STRING, kLibCrosProxyResolveName,
+ G_TYPE_INVALID, G_TYPE_INVALID)) {
+ LOG(ERROR) << "dbus_g_proxy_call failed: "
+ << utils::GetGErrorMessage(error);
+ return false;
+ }
+ callbacks_.insert(make_pair(url, make_pair(callback, data)));
+ Closure* closure = NewCallback(this,
+ &ChromeBrowserProxyResolver::HandleTimeout,
+ url);
+ GSource* timer = g_timeout_source_new_seconds(timeout_);
+ g_source_set_callback(timer, &utils::GlibRunClosure, closure, NULL);
+ g_source_attach(timer, NULL);
+ timers_.insert(make_pair(url, timer));
+ return true;
+}
+
+DBusHandlerResult ChromeBrowserProxyResolver::FilterMessage(
+ DBusConnection* connection,
+ DBusMessage* message) {
+ // Code lifted from libcros.
+ if (!dbus_->DbusMessageIsSignal(message,
+ kLibCrosProxyResolveSignalInterface,
+ kLibCrosProxyResolveName)) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ // Get args
+ char* source_url = NULL;
+ char* proxy_list = NULL;
+ char* error = NULL;
+ DBusError arg_error;
+ dbus_error_init(&arg_error);
+ if (!dbus_->DbusMessageGetArgs(message, &arg_error,
+ DBUS_TYPE_STRING, &source_url,
+ DBUS_TYPE_STRING, &proxy_list,
+ DBUS_TYPE_STRING, &error,
+ DBUS_TYPE_INVALID)) {
+ LOG(ERROR) << "Error reading dbus signal.";
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ if (!source_url || !proxy_list) {
+ LOG(ERROR) << "Error getting url, proxy list from dbus signal.";
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ HandleReply(source_url, proxy_list);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+bool ChromeBrowserProxyResolver::DeleteUrlState(
+ const string& source_url,
+ bool delete_timer,
+ pair<ProxiesResolvedFn, void*>* callback) {
+ {
+ CallbacksMap::iterator it = callbacks_.lower_bound(source_url);
+ TEST_AND_RETURN_FALSE(it != callbacks_.end());
+ TEST_AND_RETURN_FALSE(it->first == source_url);
+ if (callback)
+ *callback = it->second;
+ callbacks_.erase(it);
+ }
+ {
+ TimeoutsMap::iterator it = timers_.lower_bound(source_url);
+ TEST_AND_RETURN_FALSE(it != timers_.end());
+ TEST_AND_RETURN_FALSE(it->first == source_url);
+ if (delete_timer)
+ g_source_destroy(it->second);
+ timers_.erase(it);
+ }
+ return true;
+}
+
+void ChromeBrowserProxyResolver::HandleReply(const string& source_url,
+ const string& proxy_list) {
+ pair<ProxiesResolvedFn, void*> callback;
+ TEST_AND_RETURN(DeleteUrlState(source_url, true, &callback));
+ (*callback.first)(ParseProxyString(proxy_list), callback.second);
+}
+
+void ChromeBrowserProxyResolver::HandleTimeout(string source_url) {
+ LOG(INFO) << "Timeout handler called. Seems Chrome isn't responding.";
+ pair<ProxiesResolvedFn, void*> callback;
+ TEST_AND_RETURN(DeleteUrlState(source_url, false, &callback));
+ deque<string> proxies;
+ proxies.push_back(kNoProxy);
+ (*callback.first)(proxies, callback.second);
+}
+
+deque<string> ChromeBrowserProxyResolver::ParseProxyString(
+ const string& input) {
+ deque<string> ret;
+ // Some of this code taken from
+ // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
+ // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
+ StringTokenizer entry_tok(input, ";");
+ while (entry_tok.GetNext()) {
+ string token = entry_tok.token();
+ TrimWhitespaceASCII(token, TRIM_ALL, &token);
+
+ // Start by finding the first space (if any).
+ std::string::iterator space;
+ for (space = token.begin(); space != token.end(); ++space) {
+ if (IsAsciiWhitespace(*space)) {
+ break;
+ }
+ }
+
+ string scheme = string(token.begin(), space);
+ StringToLowerASCII(&scheme);
+ // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
+ if (scheme == "socks")
+ scheme += "4";
+ else if (scheme == "proxy")
+ scheme = "http";
+ else if (scheme != "https" &&
+ scheme != "socks4" &&
+ scheme != "socks5" &&
+ scheme != "direct")
+ continue; // Invalid proxy scheme
+
+ string host_and_port = string(space, token.end());
+ TrimWhitespaceASCII(host_and_port, TRIM_ALL, &host_and_port);
+ if (scheme != "direct" && host_and_port.empty())
+ continue; // Must supply host/port when non-direct proxy used.
+ ret.push_back(scheme + "://" + host_and_port);
+ }
+ if (ret.empty() || *ret.rbegin() != kNoProxy)
+ ret.push_back(kNoProxy);
+ return ret;
+}
+
+} // namespace chromeos_update_engine
« no previous file with comments | « chrome_browser_proxy_resolver.h ('k') | chrome_browser_proxy_resolver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698