Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / net / proxy / proxy_resolver_mojo.cc
blob89a037484489fce15fac2183fe38d3cf2058c401
1 // Copyright 2015 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.
5 #include "net/proxy/proxy_resolver_mojo.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "mojo/common/common_type_converters.h"
11 #include "mojo/common/url_type_converters.h"
12 #include "net/base/net_errors.h"
13 #include "net/dns/mojo_host_resolver_impl.h"
14 #include "net/proxy/mojo_proxy_resolver_factory.h"
15 #include "net/proxy/mojo_proxy_type_converters.h"
16 #include "net/proxy/proxy_info.h"
17 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
20 namespace net {
22 class ProxyResolverMojo::Job : public interfaces::ProxyResolverRequestClient,
23 public mojo::ErrorHandler {
24 public:
25 Job(ProxyResolverMojo* resolver,
26 const GURL& url,
27 ProxyInfo* results,
28 const CompletionCallback& callback);
29 ~Job() override;
31 // Cancels the job and prevents the callback from being run.
32 void Cancel();
34 // Returns the LoadState of this job.
35 LoadState load_state() { return load_state_; }
37 private:
38 // Overridden from mojo::ErrorHandler:
39 void OnConnectionError() override;
41 // Overridden from interfaces::ProxyResolverRequestClient:
42 void ReportResult(
43 int32_t error,
44 mojo::Array<interfaces::ProxyServerPtr> proxy_servers) override;
45 void LoadStateChanged(int32_t load_state) override;
47 ProxyResolverMojo* resolver_;
48 const GURL url_;
49 ProxyInfo* results_;
50 CompletionCallback callback_;
51 LoadState load_state_ = LOAD_STATE_RESOLVING_PROXY_FOR_URL;
53 base::ThreadChecker thread_checker_;
54 mojo::Binding<interfaces::ProxyResolverRequestClient> binding_;
57 ProxyResolverMojo::Job::Job(ProxyResolverMojo* resolver,
58 const GURL& url,
59 ProxyInfo* results,
60 const CompletionCallback& callback)
61 : resolver_(resolver),
62 url_(url),
63 results_(results),
64 callback_(callback),
65 binding_(this) {
66 binding_.set_error_handler(this);
68 interfaces::ProxyResolverRequestClientPtr client_ptr;
69 binding_.Bind(mojo::GetProxy(&client_ptr));
70 resolver_->mojo_proxy_resolver_ptr_->GetProxyForUrl(mojo::String::From(url_),
71 client_ptr.Pass());
74 ProxyResolverMojo::Job::~Job() {
75 DCHECK(thread_checker_.CalledOnValidThread());
76 if (!callback_.is_null())
77 callback_.Run(ERR_PAC_SCRIPT_TERMINATED);
80 void ProxyResolverMojo::Job::Cancel() {
81 DCHECK(thread_checker_.CalledOnValidThread());
82 DCHECK(!callback_.is_null());
83 callback_.Reset();
86 void ProxyResolverMojo::Job::OnConnectionError() {
87 DCHECK(thread_checker_.CalledOnValidThread());
88 DVLOG(1) << "ProxyResolverMojo::Job::OnConnectionError";
89 resolver_->RemoveJob(this);
92 void ProxyResolverMojo::Job::ReportResult(
93 int32_t error,
94 mojo::Array<interfaces::ProxyServerPtr> proxy_servers) {
95 DCHECK(thread_checker_.CalledOnValidThread());
96 DVLOG(1) << "ProxyResolverMojo::Job::ReportResult: " << error;
98 if (error == OK) {
99 *results_ = proxy_servers.To<ProxyInfo>();
100 DVLOG(1) << "Servers: " << results_->ToPacString();
103 callback_.Run(error);
104 callback_.Reset();
105 resolver_->RemoveJob(this);
108 void ProxyResolverMojo::Job::LoadStateChanged(int32_t load_state) {
109 load_state_ = static_cast<LoadState>(load_state);
112 ProxyResolverMojo::ProxyResolverMojo(
113 MojoProxyResolverFactory* mojo_proxy_resolver_factory,
114 HostResolver* host_resolver)
115 : ProxyResolver(true /* |expects_pac_bytes| */),
116 mojo_proxy_resolver_factory_(mojo_proxy_resolver_factory),
117 host_resolver_(host_resolver) {
120 ProxyResolverMojo::~ProxyResolverMojo() {
121 DCHECK(thread_checker_.CalledOnValidThread());
122 // All pending requests should have been cancelled.
123 DCHECK(pending_jobs_.empty());
124 DCHECK(set_pac_script_callback_.IsCancelled());
127 void ProxyResolverMojo::CancelSetPacScript() {
128 DCHECK(thread_checker_.CalledOnValidThread());
129 set_pac_script_callback_.Cancel();
132 int ProxyResolverMojo::SetPacScript(
133 const scoped_refptr<ProxyResolverScriptData>& pac_script,
134 const CompletionCallback& callback) {
135 DCHECK(thread_checker_.CalledOnValidThread());
136 DCHECK(set_pac_script_callback_.IsCancelled());
137 DCHECK(!callback.is_null());
138 if (pac_script->type() != ProxyResolverScriptData::TYPE_SCRIPT_CONTENTS ||
139 pac_script->utf16().empty()) {
140 return ERR_PAC_SCRIPT_FAILED;
143 DVLOG(1) << "ProxyResolverMojo::SetPacScript: " << pac_script->utf16();
144 set_pac_script_callback_.Reset(
145 base::Bind(&ProxyResolverMojo::OnSetPacScriptDone, base::Unretained(this),
146 pac_script, callback));
148 if (!mojo_proxy_resolver_ptr_)
149 SetUpServices();
151 mojo_proxy_resolver_ptr_->SetPacScript(
152 mojo::String::From(pac_script->utf16()),
153 set_pac_script_callback_.callback());
155 return ERR_IO_PENDING;
158 void ProxyResolverMojo::OnSetPacScriptDone(
159 const scoped_refptr<ProxyResolverScriptData>& pac_script,
160 const CompletionCallback& callback,
161 int32_t result) {
162 DCHECK(thread_checker_.CalledOnValidThread());
163 DCHECK(!set_pac_script_callback_.IsCancelled());
164 DVLOG(1) << "ProxyResolverMojo::OnSetPacScriptDone: " << result;
166 callback.Run(result);
167 set_pac_script_callback_.Cancel();
170 void ProxyResolverMojo::SetUpServices() {
171 DCHECK(thread_checker_.CalledOnValidThread());
172 // A Mojo service implementation must outlive its binding.
173 mojo_host_resolver_binding_.reset();
175 interfaces::HostResolverPtr mojo_host_resolver_ptr;
176 mojo_host_resolver_.reset(new MojoHostResolverImpl(host_resolver_));
177 mojo_host_resolver_binding_.reset(new mojo::Binding<interfaces::HostResolver>(
178 mojo_host_resolver_.get(), mojo::GetProxy(&mojo_host_resolver_ptr)));
179 mojo_proxy_resolver_ptr_.reset();
180 mojo_proxy_resolver_factory_->Create(
181 mojo::GetProxy(&mojo_proxy_resolver_ptr_), mojo_host_resolver_ptr.Pass());
182 mojo_proxy_resolver_ptr_.set_error_handler(this);
185 void ProxyResolverMojo::AbortPendingRequests() {
186 DCHECK(thread_checker_.CalledOnValidThread());
187 if (!set_pac_script_callback_.IsCancelled()) {
188 set_pac_script_callback_.callback().Run(ERR_PAC_SCRIPT_TERMINATED);
189 set_pac_script_callback_.Cancel();
192 // Need to use this loop because deleting a Job will cause its callback to be
193 // run with a failure error code, which may cause other Jobs to be deleted.
194 while (!pending_jobs_.empty()) {
195 auto it = pending_jobs_.begin();
196 Job* job = *it;
197 pending_jobs_.erase(it);
199 // Deleting the job will cause its completion callback to be run with an
200 // ERR_PAC_SCRIPT_TERMINATED error.
201 delete job;
205 void ProxyResolverMojo::OnConnectionError() {
206 DCHECK(thread_checker_.CalledOnValidThread());
207 DVLOG(1) << "ProxyResolverMojo::OnConnectionError";
209 // Disconnect from the Mojo proxy resolver service. An attempt to reconnect
210 // will happen on the next |SetPacScript()| request.
211 mojo_proxy_resolver_ptr_.reset();
213 // Aborting requests will invoke their callbacks, which may call
214 // |SetPacScript()| and re-create the connection. So disconnect from the Mojo
215 // service (above) before aborting the pending requests.
216 AbortPendingRequests();
219 void ProxyResolverMojo::RemoveJob(Job* job) {
220 DCHECK(thread_checker_.CalledOnValidThread());
221 size_t num_erased = pending_jobs_.erase(job);
222 DCHECK(num_erased);
223 delete job;
226 int ProxyResolverMojo::GetProxyForURL(const GURL& url,
227 ProxyInfo* results,
228 const CompletionCallback& callback,
229 RequestHandle* request,
230 const BoundNetLog& net_log) {
231 DCHECK(thread_checker_.CalledOnValidThread());
233 // If the Mojo service is not connected, fail. The Mojo service is connected
234 // when the script is set, which must be done after construction and after a
235 // previous request returns ERR_PAC_SCRIPT_TERMINATED due to the Mojo proxy
236 // resolver process crashing.
237 if (!mojo_proxy_resolver_ptr_) {
238 DVLOG(1) << "ProxyResolverMojo::GetProxyForURL: Mojo not connected";
239 return ERR_PAC_SCRIPT_TERMINATED;
242 Job* job = new Job(this, url, results, callback);
243 bool inserted = pending_jobs_.insert(job).second;
244 DCHECK(inserted);
245 *request = job;
247 return ERR_IO_PENDING;
250 void ProxyResolverMojo::CancelRequest(RequestHandle request) {
251 DCHECK(thread_checker_.CalledOnValidThread());
252 Job* job = static_cast<Job*>(request);
253 DCHECK(job);
254 job->Cancel();
255 RemoveJob(job);
258 LoadState ProxyResolverMojo::GetLoadState(RequestHandle request) const {
259 Job* job = static_cast<Job*>(request);
260 CHECK_EQ(1u, pending_jobs_.count(job));
261 return job->load_state();
264 } // namespace net