| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/proxy_resolution/configured_proxy_resolution_request.h" |
| |
| #include <utility> |
| |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "net/base/net_errors.h" |
| #include "net/log/net_log_event_type.h" |
| #include "net/proxy_resolution/configured_proxy_resolution_service.h" |
| #include "net/proxy_resolution/proxy_info.h" |
| |
| namespace net { |
| |
| ConfiguredProxyResolutionRequest::ConfiguredProxyResolutionRequest( |
| ConfiguredProxyResolutionService* service, |
| const GURL& url, |
| const std::string& method, |
| const NetworkAnonymizationKey& network_anonymization_key, |
| ProxyInfo* results, |
| CompletionOnceCallback user_callback, |
| const NetLogWithSource& net_log) |
| : service_(service), |
| user_callback_(std::move(user_callback)), |
| results_(results), |
| url_(url), |
| method_(method), |
| network_anonymization_key_(network_anonymization_key), |
| net_log_(net_log), |
| creation_time_(base::TimeTicks::Now()) { |
| DCHECK(!user_callback_.is_null()); |
| } |
| |
| ConfiguredProxyResolutionRequest::~ConfiguredProxyResolutionRequest() { |
| if (service_) { |
| service_->RemovePendingRequest(this); |
| net_log_.AddEvent(NetLogEventType::CANCELLED); |
| |
| if (is_started()) |
| CancelResolveJob(); |
| |
| // This should be emitted last, after any message |CancelResolveJob()| may |
| // trigger. |
| net_log_.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE); |
| } |
| } |
| |
| // Starts the resolve proxy request. |
| int ConfiguredProxyResolutionRequest::Start() { |
| DCHECK(!was_completed()); |
| DCHECK(!is_started()); |
| |
| DCHECK(service_->config_); |
| traffic_annotation_ = MutableNetworkTrafficAnnotationTag( |
| service_->config_->traffic_annotation()); |
| |
| if (service_->ApplyPacBypassRules(url_, results_)) |
| return OK; |
| |
| return service_->GetProxyResolver()->GetProxyForURL( |
| url_, network_anonymization_key_, results_, |
| base::BindOnce(&ConfiguredProxyResolutionRequest::QueryComplete, |
| base::Unretained(this)), |
| &resolve_job_, net_log_); |
| } |
| |
| void ConfiguredProxyResolutionRequest:: |
| StartAndCompleteCheckingForSynchronous() { |
| int rv = service_->TryToCompleteSynchronously(url_, results_); |
| if (rv == ERR_IO_PENDING) |
| rv = Start(); |
| if (rv != ERR_IO_PENDING) |
| QueryComplete(rv); |
| } |
| |
| void ConfiguredProxyResolutionRequest::CancelResolveJob() { |
| DCHECK(is_started()); |
| // The request may already be running in the resolver. |
| resolve_job_.reset(); |
| DCHECK(!is_started()); |
| } |
| |
| int ConfiguredProxyResolutionRequest::QueryDidComplete(int result_code) { |
| DCHECK(!was_completed()); |
| |
| // Clear |resolve_job_| so is_started() returns false while |
| // DidFinishResolvingProxy() runs. |
| resolve_job_.reset(); |
| |
| // Note that DidFinishResolvingProxy might modify |results_|. |
| int rv = service_->DidFinishResolvingProxy(url_, network_anonymization_key_, |
| method_, results_, result_code, |
| 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()); |
| |
| // If annotation is not already set, e.g. through TryToCompleteSynchronously |
| // function, use in-progress-resolve annotation. |
| if (!results_->traffic_annotation().is_valid()) |
| results_->set_traffic_annotation(traffic_annotation_); |
| |
| // If proxy is set without error, ensure that an annotation is provided. |
| if (result_code != ERR_ABORTED && !rv) |
| DCHECK(results_->traffic_annotation().is_valid()); |
| |
| // Reset the state associated with in-progress-resolve. |
| traffic_annotation_.reset(); |
| |
| return rv; |
| } |
| |
| int ConfiguredProxyResolutionRequest::QueryDidCompleteSynchronously( |
| int result_code) { |
| int rv = QueryDidComplete(result_code); |
| service_ = nullptr; |
| return rv; |
| } |
| |
| LoadState ConfiguredProxyResolutionRequest::GetLoadState() const { |
| LoadState load_state = LOAD_STATE_IDLE; |
| if (service_ && service_->GetLoadStateIfAvailable(&load_state)) |
| return load_state; |
| |
| if (is_started()) |
| return resolve_job_->GetLoadState(); |
| return LOAD_STATE_RESOLVING_PROXY_FOR_URL; |
| } |
| |
| // Callback for when the ProxyResolver request has completed. |
| void ConfiguredProxyResolutionRequest::QueryComplete(int result_code) { |
| result_code = QueryDidComplete(result_code); |
| |
| CompletionOnceCallback callback = std::move(user_callback_); |
| |
| service_->RemovePendingRequest(this); |
| service_ = nullptr; |
| user_callback_.Reset(); |
| std::move(callback).Run(result_code); |
| } |
| |
| } // namespace net |