1 // Copyright 2020 The Chromium Authors
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 "net/proxy_resolution/win/windows_system_proxy_resolution_service.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/values.h"
12 #include "base/win/windows_version.h"
13 #include "net/base/net_errors.h"
14 #include "net/log/net_log.h"
15 #include "net/log/net_log_event_type.h"
16 #include "net/log/net_log_with_source.h"
17 #include "net/proxy_resolution/win/windows_system_proxy_resolution_request.h"
18 #include "net/proxy_resolution/win/windows_system_proxy_resolver.h"
19
20 namespace net {
21
22 // static
IsSupported()23 bool WindowsSystemProxyResolutionService::IsSupported() {
24 // The sandbox required to run the WinHttp functions used in the resolver is
25 // only supported in RS1 and later.
26 if (base::win::GetVersion() < base::win::Version::WIN10_RS1) {
27 LOG(WARNING) << "WindowsSystemProxyResolutionService is only supported for "
28 "Windows 10 Version 1607 (RS1) and later.";
29 return false;
30 }
31
32 return true;
33 }
34
35 // static
36 std::unique_ptr<WindowsSystemProxyResolutionService>
Create(std::unique_ptr<WindowsSystemProxyResolver> windows_system_proxy_resolver,NetLog * net_log)37 WindowsSystemProxyResolutionService::Create(
38 std::unique_ptr<WindowsSystemProxyResolver> windows_system_proxy_resolver,
39 NetLog* net_log) {
40 if (!IsSupported() || !windows_system_proxy_resolver)
41 return nullptr;
42
43 return base::WrapUnique(new WindowsSystemProxyResolutionService(
44 std::move(windows_system_proxy_resolver), net_log));
45 }
46
WindowsSystemProxyResolutionService(std::unique_ptr<WindowsSystemProxyResolver> windows_system_proxy_resolver,NetLog * net_log)47 WindowsSystemProxyResolutionService::WindowsSystemProxyResolutionService(
48 std::unique_ptr<WindowsSystemProxyResolver> windows_system_proxy_resolver,
49 NetLog* net_log)
50 : windows_system_proxy_resolver_(std::move(windows_system_proxy_resolver)),
51 net_log_(net_log) {}
52
~WindowsSystemProxyResolutionService()53 WindowsSystemProxyResolutionService::~WindowsSystemProxyResolutionService() {
54 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
55 // Cancel any in-progress requests.
56 // This cancels the internal requests, but leaves the responsibility of
57 // canceling the high-level ProxyResolutionRequest (by deleting it) to the
58 // client. Since |pending_requests_| might be modified in one of the requests'
59 // callbacks (if it deletes another request), iterating through the set in a
60 // for-loop will not work.
61 while (!pending_requests_.empty()) {
62 WindowsSystemProxyResolutionRequest* req = *pending_requests_.begin();
63 req->ProxyResolutionComplete(ProxyList(), WinHttpStatus::kAborted, 0);
64 pending_requests_.erase(req);
65 }
66 }
67
ResolveProxy(const GURL & url,const std::string & method,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback callback,std::unique_ptr<ProxyResolutionRequest> * request,const NetLogWithSource & net_log)68 int WindowsSystemProxyResolutionService::ResolveProxy(
69 const GURL& url,
70 const std::string& method,
71 const NetworkAnonymizationKey& network_anonymization_key,
72 ProxyInfo* results,
73 CompletionOnceCallback callback,
74 std::unique_ptr<ProxyResolutionRequest>* request,
75 const NetLogWithSource& net_log) {
76 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
77 DCHECK(!callback.is_null());
78 DCHECK(request);
79
80 net_log.BeginEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
81
82 // Once it's created, the WindowsSystemProxyResolutionRequest immediately
83 // kicks off proxy resolution in a separate process.
84 auto req = std::make_unique<WindowsSystemProxyResolutionRequest>(
85 this, url, method, results, std::move(callback), net_log,
86 windows_system_proxy_resolver_.get());
87
88 DCHECK(!ContainsPendingRequest(req.get()));
89 pending_requests_.insert(req.get());
90
91 // Completion will be notified through |callback|, unless the caller cancels
92 // the request using |request|.
93 *request = std::move(req);
94 return ERR_IO_PENDING;
95 }
96
ReportSuccess(const ProxyInfo & proxy_info)97 void WindowsSystemProxyResolutionService::ReportSuccess(
98 const ProxyInfo& proxy_info) {
99 // TODO(https://crbug.com/1032820): Update proxy retry info with new proxy
100 // resolution data.
101 }
102
SetProxyDelegate(ProxyDelegate * delegate)103 void WindowsSystemProxyResolutionService::SetProxyDelegate(
104 ProxyDelegate* delegate) {
105 // TODO(https://crbug.com/1032820): Implement proxy delegates.
106 }
107
OnShutdown()108 void WindowsSystemProxyResolutionService::OnShutdown() {
109 // TODO(https://crbug.com/1032820): Add cleanup here as necessary. If cleanup
110 // is unnecessary, update the interface to not require an implementation for
111 // this so OnShutdown() can be removed.
112 }
113
ClearBadProxiesCache()114 void WindowsSystemProxyResolutionService::ClearBadProxiesCache() {
115 proxy_retry_info_.clear();
116 }
117
proxy_retry_info() const118 const ProxyRetryInfoMap& WindowsSystemProxyResolutionService::proxy_retry_info()
119 const {
120 return proxy_retry_info_;
121 }
122
GetProxyNetLogValues()123 base::Value::Dict WindowsSystemProxyResolutionService::GetProxyNetLogValues() {
124 // TODO (https://crbug.com/1032820): Implement net logs.
125 return base::Value::Dict();
126 }
127
128 bool WindowsSystemProxyResolutionService::
CastToConfiguredProxyResolutionService(ConfiguredProxyResolutionService ** configured_proxy_resolution_service)129 CastToConfiguredProxyResolutionService(
130 ConfiguredProxyResolutionService**
131 configured_proxy_resolution_service) {
132 *configured_proxy_resolution_service = nullptr;
133 return false;
134 }
135
ContainsPendingRequest(WindowsSystemProxyResolutionRequest * req)136 bool WindowsSystemProxyResolutionService::ContainsPendingRequest(
137 WindowsSystemProxyResolutionRequest* req) {
138 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
139 return pending_requests_.count(req) == 1;
140 }
141
RemovePendingRequest(WindowsSystemProxyResolutionRequest * req)142 void WindowsSystemProxyResolutionService::RemovePendingRequest(
143 WindowsSystemProxyResolutionRequest* req) {
144 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
145 DCHECK(ContainsPendingRequest(req));
146 pending_requests_.erase(req);
147 }
148
DidFinishResolvingProxy(const GURL & url,const std::string & method,ProxyInfo * result,WinHttpStatus winhttp_status,const NetLogWithSource & net_log)149 int WindowsSystemProxyResolutionService::DidFinishResolvingProxy(
150 const GURL& url,
151 const std::string& method,
152 ProxyInfo* result,
153 WinHttpStatus winhttp_status,
154 const NetLogWithSource& net_log) {
155 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
156
157 // TODO(https://crbug.com/1032820): Implement net logs.
158 // TODO(https://crbug.com/1032820): Implement proxy delegate.
159 // TODO(https://crbug.com/1032820): Implement proxy retry info.
160
161 if (winhttp_status != WinHttpStatus::kOk)
162 result->UseDirect();
163
164 net_log.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
165 return OK;
166 }
167
168 } // namespace net
169