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

Side by Side Diff: list_proxies.cc

Issue 6730021: crash-reporter: Create a list_proxies command (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/crash-reporter.git@master
Patch Set: Reorder command-line flags per codereview Created 9 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <unistd.h> // for isatty()
6
7 #include <deque>
8 #include <string>
9
10 #include <dbus/dbus-glib-lowlevel.h>
11 #include <glib.h>
12
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/string_tokenizer.h"
16 #include "base/string_util.h"
17 #include "base/values.h"
18 #include "chromeos/dbus/dbus.h"
19 #include "chromeos/syslog_logging.h"
20 #include "gflags/gflags.h"
21
22 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
23 DEFINE_bool(quiet, false, "Only print the proxies");
24 // Number of seconds to wait for browser to send us a signal
25 DEFINE_int32(timeout, 5, "Set timeout for browser resolving proxies");
26 DEFINE_bool(verbose, false, "Print additional messages even "
27 "when not run from a TTY");
28 #pragma GCC diagnostic error "-Wstrict-aliasing"
29
30 const char kLibCrosProxyResolveSignalInterface[] =
31 "org.chromium.CrashReporterLibcrosProxyResolvedInterface";
32 const char kLibCrosProxyResolveName[] = "ProxyResolved";
33 const char kLibCrosServiceInterface[] = "org.chromium.LibCrosServiceInterface";
34 const char kLibCrosServiceName[] = "org.chromium.LibCrosService";
35 const char kLibCrosServicePath[] = "/org/chromium/LibCrosService";
36 const char kLibCrosServiceResolveNetworkProxyMethodName[] =
37 "ResolveNetworkProxy";
38 const char kNoProxy[] = "direct://";
39
40 static const char *GetGErrorMessage(const GError *error) {
41 if (!error)
42 return "Unknown error.";
43 return error->message;
44 }
45
46 // Copied from src/update_engine/chrome_browser_proxy_resolver.cc
47 // Parses the browser's answer for resolved proxies. It returns a
48 // list of strings, each of which is a resolved proxy.
49 std::deque<std::string> ParseProxyString(const std::string &input) {
50 std::deque<std::string> ret;
51 // Some of this code taken from
52 // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
53 // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
54 StringTokenizer entry_tok(input, ";");
55 while (entry_tok.GetNext()) {
56 std::string token = entry_tok.token();
57 TrimWhitespaceASCII(token, TRIM_ALL, &token);
58
59 // Start by finding the first space (if any).
60 std::string::iterator space;
61 for (space = token.begin(); space != token.end(); ++space) {
62 if (IsAsciiWhitespace(*space)) {
63 break;
64 }
65 }
66
67 std::string scheme = std::string(token.begin(), space);
68 StringToLowerASCII(&scheme);
69 // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
70 if (scheme == "socks")
71 scheme += "4";
72 else if (scheme == "proxy")
73 scheme = "http";
74 else if (scheme != "https" &&
75 scheme != "socks4" &&
76 scheme != "socks5" &&
77 scheme != "direct")
78 continue; // Invalid proxy scheme
79
80 std::string host_and_port = std::string(space, token.end());
81 TrimWhitespaceASCII(host_and_port, TRIM_ALL, &host_and_port);
82 if (scheme != "direct" && host_and_port.empty())
83 continue; // Must supply host/port when non-direct proxy used.
84 ret.push_back(scheme + "://" + host_and_port);
85 }
86 if (ret.empty() || *ret.rbegin() != kNoProxy)
87 ret.push_back(kNoProxy);
88 return ret;
89 }
90
91 // Define a signal-watcher class to handle the D-Bus signal sent to us when
92 // the browser answers our request to resolve proxies.
93 class BrowserProxyResolvedSignalWatcher : public chromeos::dbus::SignalWatcher {
94 public:
95 explicit BrowserProxyResolvedSignalWatcher(GMainLoop *main_loop,
96 std::deque<std::string> *proxies)
97 : main_loop_(main_loop), proxies_(proxies) { }
98
99 virtual void OnSignal(DBusMessage *message) {
100 // Get args
101 char *source_url = NULL;
102 char *proxy_list = NULL;
103 char *error = NULL;
104 DBusError arg_error;
105 dbus_error_init(&arg_error);
106 if (!dbus_message_get_args(message, &arg_error,
107 DBUS_TYPE_STRING, &source_url,
108 DBUS_TYPE_STRING, &proxy_list,
109 DBUS_TYPE_STRING, &error,
110 DBUS_TYPE_INVALID)) {
111 LOG(ERROR) << "Error reading D-Bus signal";
112 return;
113 }
114 if (!source_url || !proxy_list) {
115 LOG(ERROR) << "Error getting url, proxy list from D-Bus signal";
116 return;
117 }
118
119 const std::deque<std::string> &proxies = ParseProxyString(proxy_list);
120 for (std::deque<std::string>::const_iterator it = proxies.begin();
121 it != proxies.end(); ++it) {
122 LOG(INFO) << "Found proxy via browser signal: " << (*it).c_str();
123 proxies_->push_back(*it);
124 }
125
126 g_main_loop_quit(main_loop_);
127 }
128
129 private:
130 GMainLoop *main_loop_;
131 std::deque<std::string> *proxies_;
132 };
133
134 static gboolean HandleBrowserTimeout(void *data) {
135 GMainLoop *main_loop = reinterpret_cast<GMainLoop *>(data);
136 LOG(ERROR) << "Timeout while waiting for browser to resolve proxy";
137 g_main_loop_quit(main_loop);
138 return false; // only call once
139 }
140
141 static bool ShowBrowserProxies(const char *url) {
142 GMainLoop *main_loop = g_main_loop_new(NULL, false);
143
144 chromeos::dbus::BusConnection dbus = chromeos::dbus::GetSystemBusConnection();
145 if (!dbus.HasConnection()) {
146 LOG(ERROR) << "Error connecting to system D-Bus";
147 return false;
148 }
149 chromeos::dbus::Proxy browser_proxy(dbus,
150 kLibCrosServiceName,
151 kLibCrosServicePath,
152 kLibCrosServiceInterface);
153 if (!browser_proxy) {
154 LOG(ERROR) << "Error creating D-Bus proxy to interface "
155 << "'" << kLibCrosServiceName << "'";
156 return false;
157 }
158
159 // Watch for a proxy-resolved signal sent to us
160 std::deque<std::string> proxies;
161 BrowserProxyResolvedSignalWatcher proxy_resolver(main_loop, &proxies);
162 proxy_resolver.StartMonitoring(kLibCrosProxyResolveSignalInterface,
163 kLibCrosProxyResolveName);
164
165 // Request the proxies for our URL. The answer is sent to us via a
166 // proxy-resolved signal.
167 GError *gerror = NULL;
168 if (!dbus_g_proxy_call(browser_proxy.gproxy(),
169 kLibCrosServiceResolveNetworkProxyMethodName,
170 &gerror,
171 G_TYPE_STRING, url,
172 G_TYPE_STRING, kLibCrosProxyResolveSignalInterface,
173 G_TYPE_STRING, kLibCrosProxyResolveName,
174 G_TYPE_INVALID, G_TYPE_INVALID)) {
175 LOG(ERROR) << "Error performing D-Bus proxy call "
176 << "'" << kLibCrosServiceResolveNetworkProxyMethodName << "'"
177 << ": " << GetGErrorMessage(gerror);
178 return false;
179 }
180
181 // Setup a timeout in case the browser doesn't respond with our signal
182 g_timeout_add_seconds(FLAGS_timeout, &HandleBrowserTimeout, main_loop);
183
184 // Loop until we either get the proxy-resolved signal, or until the
185 // timeout is reached.
186 g_main_loop_run(main_loop);
187
188 // If there are no proxies, then we failed to get the proxy-resolved
189 // signal (e.g. timeout was reached).
190 if (proxies.empty())
191 return false;
192
193 for (std::deque<std::string>::const_iterator it = proxies.begin();
194 it != proxies.end(); ++it) {
195 printf("%s\n", (*it).c_str());
196 }
197 return true;
198 }
199
200 int main(int argc, char *argv[]) {
201 google::ParseCommandLineFlags(&argc, &argv, true);
202 CommandLine::Init(argc, argv);
203
204 // Default to logging to syslog.
205 int init_flags = chromeos::kLogToSyslog;
206 // Log to stderr if a TTY (and "-quiet" wasn't passed), or if "-verbose"
207 // was passed.
208 if ((!FLAGS_quiet && isatty(STDERR_FILENO)) || FLAGS_verbose)
209 init_flags |= chromeos::kLogToStderr;
210 chromeos::InitLog(init_flags);
211
212 ::g_type_init();
213
214 const char *url = NULL;
215 if (argc >= 2) {
216 url = argv[1];
217 LOG(INFO) << "Resolving proxies for URL: " << url;
218 } else {
219 LOG(INFO) << "Resolving proxies without URL";
220 }
221
222 if (!ShowBrowserProxies(url)) {
223 LOG(ERROR) << "Error resolving proxies via the browser";
224 LOG(INFO) << "Assuming direct proxy";
225 printf("%s\n", kNoProxy);
226 }
227
228 return 0;
229 }
OLDNEW
« no previous file with comments | « Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698