blob: 742f1534346774ace45564ed7330d3fc4b47a9d9 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/proxy_resolution/win/windows_system_proxy_resolution_request.h"
#include <utility>
#include "net/base/net_errors.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_list.h"
#include "net/proxy_resolution/win/windows_system_proxy_resolution_service.h"
#include "net/proxy_resolution/win/windows_system_proxy_resolver.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace net {
namespace {
constexpr net::NetworkTrafficAnnotationTag kWindowsResolverTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("proxy_config_windows_resolver", R"(
semantics {
sender: "Proxy Config for Windows System Resolver"
description:
"Establishing a connection through a proxy server using system proxy "
"settings and Windows system proxy resolution code."
trigger:
"Whenever a network request is made when the system proxy settings "
"are used, the Windows system proxy resolver is enabled, and the "
"result indicates usage of a proxy server."
data:
"Proxy configuration."
destination: OTHER
destination_other:
"The proxy server specified in the configuration."
}
policy {
cookies_allowed: NO
setting:
"User cannot override system proxy settings, but can change them "
"through 'Advanced/System/Open proxy settings'."
policy_exception_justification:
"Using either of 'ProxyMode', 'ProxyServer', or 'ProxyPacUrl' "
"policies can set Chrome to use a specific proxy settings and avoid "
"system proxy."
})");
} // namespace
WindowsSystemProxyResolutionRequest::WindowsSystemProxyResolutionRequest(
WindowsSystemProxyResolutionService* service,
const GURL& url,
const std::string& method,
ProxyInfo* results,
CompletionOnceCallback user_callback,
const NetLogWithSource& net_log,
scoped_refptr<WindowsSystemProxyResolver> windows_system_proxy_resolver)
: windows_system_proxy_resolver_(windows_system_proxy_resolver),
service_(service),
user_callback_(std::move(user_callback)),
results_(results),
url_(url),
method_(method),
net_log_(net_log),
creation_time_(base::TimeTicks::Now()) {
DCHECK(!user_callback_.is_null());
DCHECK(windows_system_proxy_resolver_);
}
WindowsSystemProxyResolutionRequest::~WindowsSystemProxyResolutionRequest() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (service_) {
service_->RemovePendingRequest(this);
net_log_.AddEvent(NetLogEventType::CANCELLED);
if (IsStarted())
CancelResolveJob();
net_log_.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
}
}
LoadState WindowsSystemProxyResolutionRequest::GetLoadState() const {
// TODO(https://crbug.com/1032820): Consider adding a LoadState for "We're
// waiting on system APIs to do their thing".
return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
}
int WindowsSystemProxyResolutionRequest::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!was_completed());
DCHECK(!IsStarted());
// Kicks off an asynchronous call that'll eventually call back into
// AsynchronousProxyResolutionComplete() with a result.
if (!windows_system_proxy_resolver_->GetProxyForUrl(this, url_.spec()))
return ERR_FAILED;
// Asynchronous proxy resolution has begun.
return ERR_IO_PENDING;
}
void WindowsSystemProxyResolutionRequest::CancelResolveJob() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(IsStarted());
// The request may already be running in the resolver.
// TODO(https://crbug.com/1032820): Cancel callback instead of just ignoring
// it.
windows_system_proxy_resolver_->RemovePendingCallbackTarget(this);
DCHECK(!IsStarted());
}
bool WindowsSystemProxyResolutionRequest::IsStarted() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return windows_system_proxy_resolver_->HasPendingCallbackTarget(this);
}
int WindowsSystemProxyResolutionRequest::UpdateResultsOnProxyResolutionComplete(
const ProxyList& proxy_list,
int net_error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!was_completed());
results_->UseProxyList(proxy_list);
// Make sure IsStarted() returns false while DidFinishResolvingProxy() runs.
windows_system_proxy_resolver_->RemovePendingCallbackTarget(this);
// Note that DidFinishResolvingProxy might modify |results_|.
const int updated_result = service_->DidFinishResolvingProxy(
url_, method_, results_, net_error, net_log_);
// Make a note in the results which configuration was in use at the
// time of the resolve.
results_->set_proxy_resolve_start_time(creation_time_);
results_->set_proxy_resolve_end_time(base::TimeTicks::Now());
results_->set_traffic_annotation(
MutableNetworkTrafficAnnotationTag(kWindowsResolverTrafficAnnotation));
return updated_result;
}
int WindowsSystemProxyResolutionRequest::SynchronousProxyResolutionComplete(
int net_error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ProxyList proxy_list;
const int updated_result =
UpdateResultsOnProxyResolutionComplete(proxy_list, net_error);
service_ = nullptr;
return updated_result;
}
void WindowsSystemProxyResolutionRequest::AsynchronousProxyResolutionComplete(
const ProxyList& proxy_list,
int net_error,
int windows_error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// TODO(https://crbug.com/1032820): Log Windows error |windows_error|.
net_error = UpdateResultsOnProxyResolutionComplete(proxy_list, net_error);
CompletionOnceCallback callback = std::move(user_callback_);
service_->RemovePendingRequest(this);
service_ = nullptr;
user_callback_.Reset();
std::move(callback).Run(net_error);
}
} // namespace net