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

Side by Side Diff: get_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: Fix some issues per the 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.
kmixter1 2011/04/12 01:17:41 nit: I would probably choose print, list, or dump
Michael Krebs 2011/04/14 03:39:15 Done.
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
23 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
24 DEFINE_bool(quiet, false, "Only print the proxies");
25 DEFINE_bool(verbose, false, "Print additional messages even "
26 "when not run from a TTY");
27 #pragma GCC diagnostic error "-Wstrict-aliasing"
28
29
30 const char kNoProxy[] = "direct://";
31
32 // The browser's method to call to resolve proxies.
33 const char kLibCrosServiceName[] = "org.chromium.LibCrosService";
34 const char kLibCrosServicePath[] = "/org/chromium/LibCrosService";
35 const char kLibCrosServiceInterface[] = "org.chromium.LibCrosServiceInterface";
36 const char kLibCrosServiceResolveNetworkProxyMethodName[] =
37 "ResolveNetworkProxy";
38 // The signal the browser will send to us with its answer.
39 const char kLibCrosProxyResolveSignalInterface[] =
40 "org.chromium.CrashReporterLibcrosProxyResolvedInterface";
41 const char kLibCrosProxyResolveName[] = "ProxyResolved";
42
43
kmixter1 2011/04/12 01:17:41 nit: I would avoid using extra vertical white spac
Michael Krebs 2011/04/14 03:39:15 Done.
44 // Number of seconds to wait for browser to send us a signal
45 const int kBrowserTimeout = 5;
kmixter1 2011/04/12 01:17:41 Should this be a DEFINE_int32 flag?
Michael Krebs 2011/04/14 03:39:15 Done.
46
47
48 static const char *GetGErrorMessage(const GError *error) {
49 if (!error)
50 return "Unknown error.";
51 return error->message;
52 }
53
54
55 // Copied from src/update_engine/chrome_browser_proxy_resolver.cc
56 // Parses the browser's answer for resolved proxies. It returns a
57 // list of strings, each of which is a resolved proxy.
58 std::deque<std::string> ParseProxyString(const std::string &input) {
59 std::deque<std::string> ret;
60 // Some of this code taken from
61 // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
62 // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
63 StringTokenizer entry_tok(input, ";");
64 while (entry_tok.GetNext()) {
65 std::string token = entry_tok.token();
66 TrimWhitespaceASCII(token, TRIM_ALL, &token);
67
68 // Start by finding the first space (if any).
69 std::string::iterator space;
70 for (space = token.begin(); space != token.end(); ++space) {
71 if (IsAsciiWhitespace(*space)) {
72 break;
73 }
74 }
75
76 std::string scheme = std::string(token.begin(), space);
77 StringToLowerASCII(&scheme);
78 // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
79 if (scheme == "socks")
80 scheme += "4";
81 else if (scheme == "proxy")
82 scheme = "http";
83 else if (scheme != "https" &&
84 scheme != "socks4" &&
85 scheme != "socks5" &&
86 scheme != "direct")
87 continue; // Invalid proxy scheme
88
89 std::string host_and_port = std::string(space, token.end());
90 TrimWhitespaceASCII(host_and_port, TRIM_ALL, &host_and_port);
91 if (scheme != "direct" && host_and_port.empty())
92 continue; // Must supply host/port when non-direct proxy used.
93 ret.push_back(scheme + "://" + host_and_port);
94 }
95 if (ret.empty() || *ret.rbegin() != kNoProxy)
96 ret.push_back(kNoProxy);
97 return ret;
98 }
99
100 class BrowserProxyResolvedSignalWatcher : public chromeos::dbus::SignalWatcher {
kmixter1 2011/04/12 01:17:41 Add a basic class docstring.
Michael Krebs 2011/04/14 03:39:15 Is the comment that's there now okay? I couldn't
101 public:
102 explicit BrowserProxyResolvedSignalWatcher(GMainLoop *main_loop,
103 std::deque<std::string> *proxies)
104 : main_loop_(main_loop), proxies_(proxies) { }
105
106 virtual void OnSignal(DBusMessage *message) {
107 // Get args
108 char *source_url = NULL;
109 char *proxy_list = NULL;
110 char *error = NULL;
111 DBusError arg_error;
112 dbus_error_init(&arg_error);
113 if (!dbus_message_get_args(message, &arg_error,
114 DBUS_TYPE_STRING, &source_url,
115 DBUS_TYPE_STRING, &proxy_list,
116 DBUS_TYPE_STRING, &error,
117 DBUS_TYPE_INVALID)) {
118 LOG(ERROR) << "Error reading D-Bus signal";
119 return;
120 }
121 if (!source_url || !proxy_list) {
122 LOG(ERROR) << "Error getting url, proxy list from D-Bus signal";
123 return;
124 }
125
126 const std::deque<std::string> &proxies = ParseProxyString(proxy_list);
127 for (std::deque<std::string>::const_iterator it = proxies.begin();
128 it != proxies.end(); ++it) {
129 LOG(INFO) << "Found proxy via browser signal: " << (*it).c_str();
130 proxies_->push_back(*it);
131 }
132
133 g_main_loop_quit(main_loop_);
134 }
135
136 private:
137 GMainLoop *main_loop_;
138 std::deque<std::string> *proxies_;
139 };
140
141 static gboolean HandleBrowserTimeout(void *data) {
142 GMainLoop *main_loop = reinterpret_cast<GMainLoop *>(data);
143 LOG(ERROR) << "Timeout while waiting for browser to resolve proxy";
144 g_main_loop_quit(main_loop);
145 return false; // only call once
146 }
147
148 static bool ShowBrowserProxies(const char *url) {
149 GMainLoop *main_loop = g_main_loop_new(NULL, false);
150
151 chromeos::dbus::BusConnection dbus = chromeos::dbus::GetSystemBusConnection();
152 if (!dbus.HasConnection()) {
153 LOG(ERROR) << "Error connecting to system D-Bus";
154 return false;
155 }
156 chromeos::dbus::Proxy browser_proxy(dbus,
157 kLibCrosServiceName,
158 kLibCrosServicePath,
159 kLibCrosServiceInterface);
160 if (!browser_proxy) {
161 LOG(ERROR) << "Error creating D-Bus proxy to interface "
162 << "'" << kLibCrosServiceName << "'";
163 return false;
164 }
165
166 // Watch for a proxy-resolved signal sent to us
167 std::deque<std::string> proxies;
168 BrowserProxyResolvedSignalWatcher proxy_resolver(main_loop, &proxies);
169 proxy_resolver.StartMonitoring(kLibCrosProxyResolveSignalInterface,
170 kLibCrosProxyResolveName);
171
172 // Request the proxies for our URL. The answer is sent to us via a
173 // proxy-resolved signal.
174 GError *gerror = NULL;
175 if (!dbus_g_proxy_call(browser_proxy.gproxy(),
176 kLibCrosServiceResolveNetworkProxyMethodName,
177 &gerror,
178 G_TYPE_STRING, url,
179 G_TYPE_STRING, kLibCrosProxyResolveSignalInterface,
180 G_TYPE_STRING, kLibCrosProxyResolveName,
181 G_TYPE_INVALID, G_TYPE_INVALID)) {
182 LOG(ERROR) << "Error performing D-Bus proxy call "
183 << "'" << kLibCrosServiceResolveNetworkProxyMethodName << "'"
184 << ": " << GetGErrorMessage(gerror);
185 return false;
186 }
187
188 // Setup a timeout in case the browser doesn't respond with our signal
189 g_timeout_add_seconds(kBrowserTimeout, &HandleBrowserTimeout, main_loop);
190
191 // Loop until we either get the proxy-resolved signal, or until the
192 // timeout is reached.
193 g_main_loop_run(main_loop);
194
195 for (std::deque<std::string>::const_iterator it = proxies.begin();
196 it != proxies.end(); ++it) {
197 g_print("%s\n", (*it).c_str());
198 }
199
200 return true;
201 }
202
203
204 int main(int argc, char *argv[]) {
205 google::ParseCommandLineFlags(&argc, &argv, true);
206 CommandLine::Init(argc, argv);
207
208 // Default to logging to syslog.
209 int init_flags = chromeos::kLogToSyslog;
210 // Log to stderr if a TTY (and "-quiet" wasn't passed), or if "-verbose"
211 // was passed.
212 if ((!FLAGS_quiet && isatty(STDERR_FILENO)) || FLAGS_verbose)
213 init_flags |= chromeos::kLogToStderr;
214 chromeos::InitLog(init_flags);
215
216 ::g_type_init();
217
218 const char *url = (argc >= 2) ? argv[1] : NULL;
kmixter1 2011/04/12 01:17:41 Would generally say to const char *url = NULL; if
Michael Krebs 2011/04/14 03:39:15 Done.
219
220 LOG(INFO) << "Resolving proxies for URL: " << (url ? url : "<n/a>");
kmixter1 2011/04/12 01:17:41 add explicit comparison to NULL for local style.
Michael Krebs 2011/04/14 03:39:15 Moot after above change.
221
222 if (!ShowBrowserProxies(url)) {
223 LOG(ERROR) << "Error resolving proxies via the browser";
224 LOG(INFO) << "Assuming direct proxy";
225 g_print("%s\n", kNoProxy);
kmixter1 2011/04/12 01:17:41 Why g_print vs printf?
Michael Krebs 2011/04/14 03:39:15 Done.
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