xref: /aosp_15_r20/external/libbrillo/brillo/http/http_proxy.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1 // Copyright 2017 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 <brillo/http/http_proxy.h>
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include <base/bind.h>
13 #include <base/callback.h>
14 #include <base/logging.h>
15 #include <base/strings/string_tokenizer.h>
16 #include <base/strings/string_util.h>
17 #include <brillo/http/http_transport.h>
18 #include <chromeos/dbus/service_constants.h>
19 #include <dbus/bus.h>
20 #include <dbus/message.h>
21 #include <dbus/object_proxy.h>
22 
23 namespace {
ParseProxyInfo(dbus::Response * response,std::vector<std::string> * proxies_out)24 bool ParseProxyInfo(dbus::Response* response,
25                     std::vector<std::string>* proxies_out) {
26   DCHECK(proxies_out);
27   if (!response) {
28     LOG(ERROR) << chromeos::kNetworkProxyServiceName << " D-Bus call to "
29                << chromeos::kNetworkProxyServiceResolveProxyMethod
30                << " failed";
31     proxies_out->assign({brillo::http::kDirectProxy});
32     return false;
33   }
34   dbus::MessageReader reader(response);
35   std::string proxy_info;
36   std::string proxy_err;
37   if (!reader.PopString(&proxy_info) || !reader.PopString(&proxy_err)) {
38     LOG(ERROR) << chromeos::kNetworkProxyServiceName << " D-Bus call to "
39                << chromeos::kNetworkProxyServiceResolveProxyMethod
40                << " returned an invalid D-Bus response";
41     proxies_out->assign({brillo::http::kDirectProxy});
42     return false;
43   }
44   if (!proxy_err.empty()) {
45     // This case occurs when on the Chrome side of things it can't connect to
46     // the proxy resolver service, we just let this fall through and will end
47     // up returning success with only the direct proxy listed.
48     LOG(WARNING) << "Got error resolving proxy: " << proxy_err;
49   }
50 
51   base::StringTokenizer toker(proxy_info, ";");
52   while (toker.GetNext()) {
53     std::string token = toker.token();
54     base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
55 
56     // Start by finding the first space (if any).
57     std::string::iterator space;
58     for (space = ++token.begin(); space != token.end(); ++space) {
59       if (base::IsAsciiWhitespace(*space)) {
60         break;
61       }
62     }
63 
64     std::string scheme = base::ToLowerASCII(std::string(token.begin(), space));
65     // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
66     if (scheme == "socks") {
67       scheme += "4";
68     } else if (scheme == "proxy") {
69       scheme = "http";
70     } else if (scheme != "https" && scheme != "socks4" && scheme != "socks5" &&
71                scheme != "direct") {
72       LOG(ERROR) << "Invalid proxy scheme found of: " << scheme;
73       continue;
74     }
75 
76     std::string host_and_port = std::string(space, token.end());
77     base::TrimWhitespaceASCII(host_and_port, base::TRIM_ALL, &host_and_port);
78     if (scheme != "direct" && host_and_port.empty()) {
79       LOG(ERROR) << "Invalid host/port information for proxy: " << token;
80       continue;
81     }
82     proxies_out->push_back(scheme + "://" + host_and_port);
83   }
84   // Always add the direct proxy (i.e. no proxy) as a last resort if not there.
85   if (proxies_out->empty() ||
86       proxies_out->back() != brillo::http::kDirectProxy) {
87     proxies_out->push_back(brillo::http::kDirectProxy);
88   }
89   return true;
90 }
91 
OnResolveProxy(const brillo::http::GetChromeProxyServersCallback & callback,dbus::Response * response)92 void OnResolveProxy(const brillo::http::GetChromeProxyServersCallback& callback,
93                     dbus::Response* response) {
94   std::vector<std::string> proxies;
95   bool result = ParseProxyInfo(response, &proxies);
96   callback.Run(result, std::move(proxies));
97 }
98 }  // namespace
99 
100 namespace brillo {
101 namespace http {
102 
GetChromeProxyServers(scoped_refptr<dbus::Bus> bus,const std::string & url,std::vector<std::string> * proxies_out)103 bool GetChromeProxyServers(scoped_refptr<dbus::Bus> bus, const std::string& url,
104                            std::vector<std::string>* proxies_out) {
105   dbus::ObjectProxy* proxy =
106       bus->GetObjectProxy(chromeos::kNetworkProxyServiceName,
107                           dbus::ObjectPath(chromeos::kNetworkProxyServicePath));
108   dbus::MethodCall method_call(
109       chromeos::kNetworkProxyServiceInterface,
110       chromeos::kNetworkProxyServiceResolveProxyMethod);
111   dbus::MessageWriter writer(&method_call);
112   writer.AppendString(url);
113   std::unique_ptr<dbus::Response> response = proxy->CallMethodAndBlock(
114       &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
115   return ParseProxyInfo(response.get(), proxies_out);
116 }
117 
GetChromeProxyServersAsync(scoped_refptr<dbus::Bus> bus,const std::string & url,const GetChromeProxyServersCallback & callback)118 void GetChromeProxyServersAsync(scoped_refptr<dbus::Bus> bus,
119                                 const std::string& url,
120                                 const GetChromeProxyServersCallback& callback) {
121   dbus::ObjectProxy* proxy = bus->GetObjectProxy(
122       chromeos::kNetworkProxyServiceName,
123       dbus::ObjectPath(chromeos::kNetworkProxyServicePath));
124   dbus::MethodCall method_call(
125       chromeos::kNetworkProxyServiceInterface,
126       chromeos::kNetworkProxyServiceResolveProxyMethod);
127   dbus::MessageWriter writer(&method_call);
128   writer.AppendString(url);
129   proxy->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
130                     base::Bind(&OnResolveProxy, callback));
131 }
132 
133 }  // namespace http
134 }  // namespace brillo
135