• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2011 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "update_engine/chrome_browser_proxy_resolver.h"
18 
19 #include <utility>
20 
21 #include <base/bind.h>
22 #include <base/memory/ptr_util.h>
23 #include <base/strings/string_tokenizer.h>
24 #include <base/strings/string_util.h>
25 
26 #include "network_proxy/dbus-proxies.h"
27 
28 namespace chromeos_update_engine {
29 
30 using base::StringTokenizer;
31 using std::deque;
32 using std::string;
33 
34 namespace {
35 
36 // Timeout for D-Bus calls in milliseconds.
37 constexpr int kTimeoutMs = 5000;
38 
39 }  // namespace
40 
ChromeBrowserProxyResolver(org::chromium::NetworkProxyServiceInterfaceProxyInterface * dbus_proxy)41 ChromeBrowserProxyResolver::ChromeBrowserProxyResolver(
42     org::chromium::NetworkProxyServiceInterfaceProxyInterface* dbus_proxy)
43     : dbus_proxy_(dbus_proxy),
44       next_request_id_(kProxyRequestIdNull + 1),
45       weak_ptr_factory_(this) {}
46 
47 ChromeBrowserProxyResolver::~ChromeBrowserProxyResolver() = default;
48 
49 // static
ParseProxyString(const string & input)50 deque<string> ChromeBrowserProxyResolver::ParseProxyString(
51     const string& input) {
52   deque<string> ret;
53   // Some of this code taken from
54   // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
55   // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
56   StringTokenizer entry_tok(input, ";");
57   while (entry_tok.GetNext()) {
58     string token = entry_tok.token();
59     base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
60 
61     // Start by finding the first space (if any).
62     string::iterator space;
63     for (space = token.begin(); space != token.end(); ++space) {
64       if (base::IsAsciiWhitespace(*space)) {
65         break;
66       }
67     }
68 
69     string scheme = base::ToLowerASCII(string(token.begin(), space));
70     // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
71     if (scheme == "socks")
72       scheme += "4";
73     else if (scheme == "proxy")
74       scheme = "http";
75     else if (scheme != "https" &&
76              scheme != "socks4" &&
77              scheme != "socks5" &&
78              scheme != "direct")
79       continue;  // Invalid proxy scheme
80 
81     string host_and_port = string(space, token.end());
82     base::TrimWhitespaceASCII(host_and_port, base::TRIM_ALL, &host_and_port);
83     if (scheme != "direct" && host_and_port.empty())
84       continue;  // Must supply host/port when non-direct proxy used.
85     ret.push_back(scheme + "://" + host_and_port);
86   }
87   if (ret.empty() || *ret.rbegin() != kNoProxy)
88     ret.push_back(kNoProxy);
89   return ret;
90 }
91 
GetProxiesForUrl(const string & url,const ProxiesResolvedFn & callback)92 ProxyRequestId ChromeBrowserProxyResolver::GetProxiesForUrl(
93     const string& url, const ProxiesResolvedFn& callback) {
94   const ProxyRequestId id = next_request_id_++;
95   dbus_proxy_->ResolveProxyAsync(
96       url,
97       base::Bind(&ChromeBrowserProxyResolver::OnResolveProxyResponse,
98                  weak_ptr_factory_.GetWeakPtr(), id),
99       base::Bind(&ChromeBrowserProxyResolver::OnResolveProxyError,
100                  weak_ptr_factory_.GetWeakPtr(), id),
101       kTimeoutMs);
102   pending_callbacks_[id] = callback;
103   return id;
104 }
105 
CancelProxyRequest(ProxyRequestId request)106 bool ChromeBrowserProxyResolver::CancelProxyRequest(ProxyRequestId request) {
107   return pending_callbacks_.erase(request) != 0;
108 }
109 
OnResolveProxyResponse(ProxyRequestId request_id,const std::string & proxy_info,const std::string & error_message)110 void ChromeBrowserProxyResolver::OnResolveProxyResponse(
111     ProxyRequestId request_id,
112     const std::string& proxy_info,
113     const std::string& error_message) {
114   if (!error_message.empty())
115     LOG(WARNING) << "Got error resolving proxy: " << error_message;
116   RunCallback(request_id, ParseProxyString(proxy_info));
117 }
118 
OnResolveProxyError(ProxyRequestId request_id,brillo::Error * error)119 void ChromeBrowserProxyResolver::OnResolveProxyError(ProxyRequestId request_id,
120                                                      brillo::Error* error) {
121   LOG(WARNING) << "Failed to resolve proxy: "
122                << (error ? error->GetMessage() : "[null]");
123   RunCallback(request_id, deque<string>{kNoProxy});
124 }
125 
RunCallback(ProxyRequestId request_id,const std::deque<std::string> & proxies)126 void ChromeBrowserProxyResolver::RunCallback(
127     ProxyRequestId request_id,
128     const std::deque<std::string>& proxies) {
129   auto it = pending_callbacks_.find(request_id);
130   if (it == pending_callbacks_.end())
131     return;
132 
133   ProxiesResolvedFn callback = it->second;
134   pending_callbacks_.erase(it);
135   callback.Run(proxies);
136 }
137 
138 } // namespace chromeos_update_engine
139