xref: /aosp_15_r20/external/cronet/net/proxy_resolution/configured_proxy_resolution_request.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/configured_proxy_resolution_request.h"
6 
7 #include <utility>
8 
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "net/base/net_errors.h"
12 #include "net/log/net_log_event_type.h"
13 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
14 #include "net/proxy_resolution/proxy_info.h"
15 
16 namespace net {
17 
ConfiguredProxyResolutionRequest(ConfiguredProxyResolutionService * service,const GURL & url,const std::string & method,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback user_callback,const NetLogWithSource & net_log)18 ConfiguredProxyResolutionRequest::ConfiguredProxyResolutionRequest(
19     ConfiguredProxyResolutionService* service,
20     const GURL& url,
21     const std::string& method,
22     const NetworkAnonymizationKey& network_anonymization_key,
23     ProxyInfo* results,
24     CompletionOnceCallback user_callback,
25     const NetLogWithSource& net_log)
26     : service_(service),
27       user_callback_(std::move(user_callback)),
28       results_(results),
29       url_(url),
30       method_(method),
31       network_anonymization_key_(network_anonymization_key),
32       net_log_(net_log),
33       creation_time_(base::TimeTicks::Now()) {
34   DCHECK(!user_callback_.is_null());
35 }
36 
~ConfiguredProxyResolutionRequest()37 ConfiguredProxyResolutionRequest::~ConfiguredProxyResolutionRequest() {
38   if (service_) {
39     service_->RemovePendingRequest(this);
40     net_log_.AddEvent(NetLogEventType::CANCELLED);
41 
42     if (is_started())
43       CancelResolveJob();
44 
45     // This should be emitted last, after any message |CancelResolveJob()| may
46     // trigger.
47     net_log_.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
48   }
49 }
50 
51 // Starts the resolve proxy request.
Start()52 int ConfiguredProxyResolutionRequest::Start() {
53   DCHECK(!was_completed());
54   DCHECK(!is_started());
55 
56   DCHECK(service_->config_);
57   traffic_annotation_ = MutableNetworkTrafficAnnotationTag(
58       service_->config_->traffic_annotation());
59 
60   if (service_->ApplyPacBypassRules(url_, results_))
61     return OK;
62 
63   return service_->GetProxyResolver()->GetProxyForURL(
64       url_, network_anonymization_key_, results_,
65       base::BindOnce(&ConfiguredProxyResolutionRequest::QueryComplete,
66                      base::Unretained(this)),
67       &resolve_job_, net_log_);
68 }
69 
70 void ConfiguredProxyResolutionRequest::
StartAndCompleteCheckingForSynchronous()71     StartAndCompleteCheckingForSynchronous() {
72   int rv = service_->TryToCompleteSynchronously(url_, results_);
73   if (rv == ERR_IO_PENDING)
74     rv = Start();
75   if (rv != ERR_IO_PENDING)
76     QueryComplete(rv);
77 }
78 
CancelResolveJob()79 void ConfiguredProxyResolutionRequest::CancelResolveJob() {
80   DCHECK(is_started());
81   // The request may already be running in the resolver.
82   resolve_job_.reset();
83   DCHECK(!is_started());
84 }
85 
QueryDidComplete(int result_code)86 int ConfiguredProxyResolutionRequest::QueryDidComplete(int result_code) {
87   DCHECK(!was_completed());
88 
89   // Clear |resolve_job_| so is_started() returns false while
90   // DidFinishResolvingProxy() runs.
91   resolve_job_.reset();
92 
93   // Note that DidFinishResolvingProxy might modify |results_|.
94   int rv = service_->DidFinishResolvingProxy(url_, network_anonymization_key_,
95                                              method_, results_, result_code,
96                                              net_log_);
97 
98   // Make a note in the results which configuration was in use at the
99   // time of the resolve.
100   results_->set_proxy_resolve_start_time(creation_time_);
101   results_->set_proxy_resolve_end_time(base::TimeTicks::Now());
102 
103   // If annotation is not already set, e.g. through TryToCompleteSynchronously
104   // function, use in-progress-resolve annotation.
105   if (!results_->traffic_annotation().is_valid())
106     results_->set_traffic_annotation(traffic_annotation_);
107 
108   // If proxy is set without error, ensure that an annotation is provided.
109   if (result_code != ERR_ABORTED && !rv)
110     DCHECK(results_->traffic_annotation().is_valid());
111 
112   // Reset the state associated with in-progress-resolve.
113   traffic_annotation_.reset();
114 
115   return rv;
116 }
117 
QueryDidCompleteSynchronously(int result_code)118 int ConfiguredProxyResolutionRequest::QueryDidCompleteSynchronously(
119     int result_code) {
120   int rv = QueryDidComplete(result_code);
121   service_ = nullptr;
122   return rv;
123 }
124 
GetLoadState() const125 LoadState ConfiguredProxyResolutionRequest::GetLoadState() const {
126   LoadState load_state = LOAD_STATE_IDLE;
127   if (service_ && service_->GetLoadStateIfAvailable(&load_state))
128     return load_state;
129 
130   if (is_started())
131     return resolve_job_->GetLoadState();
132   return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
133 }
134 
135 // Callback for when the ProxyResolver request has completed.
QueryComplete(int result_code)136 void ConfiguredProxyResolutionRequest::QueryComplete(int result_code) {
137   result_code = QueryDidComplete(result_code);
138 
139   CompletionOnceCallback callback = std::move(user_callback_);
140 
141   service_->RemovePendingRequest(this);
142   service_ = nullptr;
143   user_callback_.Reset();
144   std::move(callback).Run(result_code);
145 }
146 
147 }  // namespace net
148