blob: 12a83280c9c1cb95ad250d5e8a717a2bfca71076 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
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//
Andrew de los Reyes000d8952011-03-02 15:21:14 -080016
17#include "update_engine/chrome_browser_proxy_resolver.h"
18
Daniel Erate5f6f252017-04-20 12:09:58 -060019#include <utility>
Andrew de los Reyes000d8952011-03-02 15:21:14 -080020
Alex Vakulenko4906c1c2014-08-21 13:17:44 -070021#include <base/bind.h>
Daniel Erate5f6f252017-04-20 12:09:58 -060022#include <base/memory/ptr_util.h>
Chris Sosafc661a12013-02-26 14:43:21 -080023#include <base/strings/string_tokenizer.h>
Alex Deymoc4acdf42014-05-28 21:07:10 -070024#include <base/strings/string_util.h>
Andrew de los Reyes000d8952011-03-02 15:21:14 -080025
Daniel Erate5f6f252017-04-20 12:09:58 -060026#include "network_proxy/dbus-proxies.h"
Andrew de los Reyes000d8952011-03-02 15:21:14 -080027
28namespace chromeos_update_engine {
29
Chris Sosafc661a12013-02-26 14:43:21 -080030using base::StringTokenizer;
Andrew de los Reyes000d8952011-03-02 15:21:14 -080031using std::deque;
Andrew de los Reyes000d8952011-03-02 15:21:14 -080032using std::string;
33
Andrew de los Reyes000d8952011-03-02 15:21:14 -080034namespace {
Gilad Arnoldb752fb32014-03-03 12:23:39 -080035
Daniel Erate5f6f252017-04-20 12:09:58 -060036// Timeout for D-Bus calls in milliseconds.
37constexpr int kTimeoutMs = 5000;
Andrew de los Reyes000d8952011-03-02 15:21:14 -080038
Alex Vakulenkod2779df2014-06-16 13:19:00 -070039} // namespace
Andrew de los Reyes000d8952011-03-02 15:21:14 -080040
Gilad Arnold1b9d6ae2014-03-03 13:46:07 -080041ChromeBrowserProxyResolver::ChromeBrowserProxyResolver(
Daniel Erate5f6f252017-04-20 12:09:58 -060042 org::chromium::NetworkProxyServiceInterfaceProxyInterface* dbus_proxy)
43 : dbus_proxy_(dbus_proxy),
44 next_request_id_(kProxyRequestIdNull + 1),
45 weak_ptr_factory_(this) {}
Andrew de los Reyes000d8952011-03-02 15:21:14 -080046
Daniel Erate5f6f252017-04-20 12:09:58 -060047ChromeBrowserProxyResolver::~ChromeBrowserProxyResolver() = default;
Andrew de los Reyes000d8952011-03-02 15:21:14 -080048
Daniel Erate5f6f252017-04-20 12:09:58 -060049// static
Andrew de los Reyes000d8952011-03-02 15:21:14 -080050deque<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();
Ben Chan736fcb52014-05-21 18:28:22 -070059 base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
Andrew de los Reyes000d8952011-03-02 15:21:14 -080060
61 // Start by finding the first space (if any).
Alex Deymof329b932014-10-30 01:37:48 -070062 string::iterator space;
Andrew de los Reyes000d8952011-03-02 15:21:14 -080063 for (space = token.begin(); space != token.end(); ++space) {
Alex Vakulenkoa3cf75a2016-01-20 07:56:15 -080064 if (base::IsAsciiWhitespace(*space)) {
Andrew de los Reyes000d8952011-03-02 15:21:14 -080065 break;
66 }
67 }
68
Alex Vakulenkoa3cf75a2016-01-20 07:56:15 -080069 string scheme = base::ToLowerASCII(string(token.begin(), space));
Andrew de los Reyes000d8952011-03-02 15:21:14 -080070 // 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());
Ben Chan736fcb52014-05-21 18:28:22 -070082 base::TrimWhitespaceASCII(host_and_port, base::TRIM_ALL, &host_and_port);
Andrew de los Reyes000d8952011-03-02 15:21:14 -080083 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
Daniel Erate5f6f252017-04-20 12:09:58 -060092ProxyRequestId 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
106bool ChromeBrowserProxyResolver::CancelProxyRequest(ProxyRequestId request) {
107 return pending_callbacks_.erase(request) != 0;
108}
109
110void 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
119void 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
126void 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