blob: 88b06c43dbaf1f581b8770287515243b8f6f0db2 [file] [log] [blame]
Nicolas Arciniega9d383312020-02-18 23:36:411// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Nicolas Arciniegabc393102020-03-20 23:47:575#include "net/proxy_resolution/configured_proxy_resolution_request.h"
Nicolas Arciniega9d383312020-02-18 23:36:416
7#include <utility>
8
9#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3510#include "base/callback_helpers.h"
Nicolas Arciniega9d383312020-02-18 23:36:4111#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
16namespace net {
17
Nicolas Arciniegabc393102020-03-20 23:47:5718ConfiguredProxyResolutionRequest::ConfiguredProxyResolutionRequest(
Nicolas Arciniega9d383312020-02-18 23:36:4119 ConfiguredProxyResolutionService* service,
20 const GURL& url,
21 const std::string& method,
22 const NetworkIsolationKey& network_isolation_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_isolation_key_(network_isolation_key),
32 resolve_job_(nullptr),
33 net_log_(net_log),
34 creation_time_(base::TimeTicks::Now()) {
35 DCHECK(!user_callback_.is_null());
36}
37
Nicolas Arciniegabc393102020-03-20 23:47:5738ConfiguredProxyResolutionRequest::~ConfiguredProxyResolutionRequest() {
Nicolas Arciniega9d383312020-02-18 23:36:4139 if (service_) {
40 service_->RemovePendingRequest(this);
41 net_log_.AddEvent(NetLogEventType::CANCELLED);
42
43 if (is_started())
44 CancelResolveJob();
45
46 // This should be emitted last, after any message |CancelResolveJob()| may
47 // trigger.
48 net_log_.EndEvent(NetLogEventType::PROXY_RESOLUTION_SERVICE);
49 }
50}
51
52// Starts the resolve proxy request.
Nicolas Arciniegabc393102020-03-20 23:47:5753int ConfiguredProxyResolutionRequest::Start() {
Nicolas Arciniega9d383312020-02-18 23:36:4154 DCHECK(!was_completed());
55 DCHECK(!is_started());
56
57 DCHECK(service_->config_);
58 traffic_annotation_ = MutableNetworkTrafficAnnotationTag(
59 service_->config_->traffic_annotation());
60
61 if (service_->ApplyPacBypassRules(url_, results_))
62 return OK;
63
64 return service_->GetProxyResolver()->GetProxyForURL(
65 url_, network_isolation_key_, results_,
Nicolas Arciniegabc393102020-03-20 23:47:5766 base::BindOnce(&ConfiguredProxyResolutionRequest::QueryComplete,
Nicolas Arciniega9d383312020-02-18 23:36:4167 base::Unretained(this)),
68 &resolve_job_, net_log_);
69}
70
Nicolas Arciniegabc393102020-03-20 23:47:5771void ConfiguredProxyResolutionRequest::
72 StartAndCompleteCheckingForSynchronous() {
Nicolas Arciniega9d383312020-02-18 23:36:4173 int rv = service_->TryToCompleteSynchronously(url_, results_);
74 if (rv == ERR_IO_PENDING)
75 rv = Start();
76 if (rv != ERR_IO_PENDING)
77 QueryComplete(rv);
78}
79
Nicolas Arciniegabc393102020-03-20 23:47:5780void ConfiguredProxyResolutionRequest::CancelResolveJob() {
Nicolas Arciniega9d383312020-02-18 23:36:4181 DCHECK(is_started());
82 // The request may already be running in the resolver.
83 resolve_job_.reset();
84 DCHECK(!is_started());
85}
86
Nicolas Arciniegabc393102020-03-20 23:47:5787int ConfiguredProxyResolutionRequest::QueryDidComplete(int result_code) {
Nicolas Arciniega9d383312020-02-18 23:36:4188 DCHECK(!was_completed());
89
90 // Clear |resolve_job_| so is_started() returns false while
91 // DidFinishResolvingProxy() runs.
92 resolve_job_.reset();
93
94 // Note that DidFinishResolvingProxy might modify |results_|.
95 int rv = service_->DidFinishResolvingProxy(url_, method_, results_,
96 result_code, net_log_);
97
98 // Make a note in the results which configuration was in use at the
99 // time of the resolve.
Nicolas Arciniegabc393102020-03-20 23:47:57100 results_->set_proxy_resolve_start_time(creation_time_);
101 results_->set_proxy_resolve_end_time(base::TimeTicks::Now());
Nicolas Arciniega9d383312020-02-18 23:36:41102
103 // If annotation is not already set, e.g. through TryToCompleteSynchronously
104 // function, use in-progress-resolve annotation.
Nicolas Arciniegabc393102020-03-20 23:47:57105 if (!results_->traffic_annotation().is_valid())
Nicolas Arciniega9d383312020-02-18 23:36:41106 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)
Nicolas Arciniegabc393102020-03-20 23:47:57110 DCHECK(results_->traffic_annotation().is_valid());
Nicolas Arciniega9d383312020-02-18 23:36:41111
112 // Reset the state associated with in-progress-resolve.
113 traffic_annotation_.reset();
114
115 return rv;
116}
117
Nicolas Arciniegabc393102020-03-20 23:47:57118int ConfiguredProxyResolutionRequest::QueryDidCompleteSynchronously(
119 int result_code) {
Nicolas Arciniega9d383312020-02-18 23:36:41120 int rv = QueryDidComplete(result_code);
121 service_ = nullptr;
122 return rv;
123}
124
Nicolas Arciniegabc393102020-03-20 23:47:57125LoadState ConfiguredProxyResolutionRequest::GetLoadState() const {
Nicolas Arciniega9d383312020-02-18 23:36:41126 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.
Nicolas Arciniegabc393102020-03-20 23:47:57136void ConfiguredProxyResolutionRequest::QueryComplete(int result_code) {
Nicolas Arciniega9d383312020-02-18 23:36:41137 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