Roll src/third_party/WebKit a2aeeb7:6373c4f (svn 198318:198336)
[chromium-blink-merge.git] / net / proxy / proxy_resolver_factory_mojo.cc
bloba1ff691626fff0cb8356239bdd9d4c38e976733c
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_factory_mojo.h"
7 #include <set>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "base/threading/thread_checker.h"
13 #include "mojo/common/common_type_converters.h"
14 #include "mojo/common/url_type_converters.h"
15 #include "net/base/load_states.h"
16 #include "net/base/net_errors.h"
17 #include "net/dns/mojo_host_resolver_impl.h"
18 #include "net/interfaces/host_resolver_service.mojom.h"
19 #include "net/interfaces/proxy_resolver_service.mojom.h"
20 #include "net/proxy/mojo_proxy_resolver_factory.h"
21 #include "net/proxy/mojo_proxy_type_converters.h"
22 #include "net/proxy/proxy_info.h"
23 #include "net/proxy/proxy_resolver.h"
24 #include "net/proxy/proxy_resolver_error_observer.h"
25 #include "net/proxy/proxy_resolver_script_data.h"
26 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
28 namespace net {
29 namespace {
31 class ErrorObserverHolder : public interfaces::ProxyResolverErrorObserver {
32 public:
33 ErrorObserverHolder(
34 scoped_ptr<net::ProxyResolverErrorObserver> error_observer,
35 mojo::InterfaceRequest<interfaces::ProxyResolverErrorObserver> request);
36 ~ErrorObserverHolder() override;
38 void OnPacScriptError(int32_t line_number,
39 const mojo::String& error) override;
41 private:
42 scoped_ptr<net::ProxyResolverErrorObserver> error_observer_;
43 mojo::Binding<interfaces::ProxyResolverErrorObserver> binding_;
45 DISALLOW_COPY_AND_ASSIGN(ErrorObserverHolder);
48 ErrorObserverHolder::ErrorObserverHolder(
49 scoped_ptr<net::ProxyResolverErrorObserver> error_observer,
50 mojo::InterfaceRequest<interfaces::ProxyResolverErrorObserver> request)
51 : error_observer_(error_observer.Pass()), binding_(this, request.Pass()) {
54 ErrorObserverHolder::~ErrorObserverHolder() = default;
56 void ErrorObserverHolder::OnPacScriptError(int32_t line_number,
57 const mojo::String& error) {
58 DCHECK(error_observer_);
59 error_observer_->OnPACScriptError(line_number, error.To<base::string16>());
62 // Implementation of ProxyResolver that connects to a Mojo service to evaluate
63 // PAC scripts. This implementation only knows about Mojo services, and
64 // therefore that service may live in or out of process.
66 // This implementation reports disconnections from the Mojo service (i.e. if the
67 // service is out-of-process and that process crashes) using the error code
68 // ERR_PAC_SCRIPT_TERMINATED.
69 class ProxyResolverMojo : public ProxyResolver {
70 public:
71 // Constructs a ProxyResolverMojo that connects to a mojo proxy resolver
72 // implementation using |resolver_ptr|. The implementation uses
73 // |host_resolver| as the DNS resolver, using |host_resolver_binding| to
74 // communicate with it. When deleted, the closure contained within
75 // |on_delete_callback_runner| will be run.
76 // TODO(amistry): Add NetLog.
77 ProxyResolverMojo(
78 interfaces::ProxyResolverPtr resolver_ptr,
79 scoped_ptr<interfaces::HostResolver> host_resolver,
80 scoped_ptr<mojo::Binding<interfaces::HostResolver>> host_resolver_binding,
81 scoped_ptr<base::ScopedClosureRunner> on_delete_callback_runner,
82 scoped_ptr<ErrorObserverHolder> error_observer);
83 ~ProxyResolverMojo() override;
85 // ProxyResolver implementation:
86 int GetProxyForURL(const GURL& url,
87 ProxyInfo* results,
88 const net::CompletionCallback& callback,
89 RequestHandle* request,
90 const BoundNetLog& net_log) override;
91 void CancelRequest(RequestHandle request) override;
92 LoadState GetLoadState(RequestHandle request) const override;
94 private:
95 class Job;
97 // Mojo error handler.
98 void OnConnectionError();
100 void RemoveJob(Job* job);
102 // Connection to the Mojo proxy resolver.
103 interfaces::ProxyResolverPtr mojo_proxy_resolver_ptr_;
105 // Mojo host resolver service and binding.
106 scoped_ptr<interfaces::HostResolver> mojo_host_resolver_;
107 scoped_ptr<mojo::Binding<interfaces::HostResolver>>
108 mojo_host_resolver_binding_;
110 scoped_ptr<ErrorObserverHolder> error_observer_;
112 std::set<Job*> pending_jobs_;
114 base::ThreadChecker thread_checker_;
116 scoped_ptr<base::ScopedClosureRunner> on_delete_callback_runner_;
118 DISALLOW_COPY_AND_ASSIGN(ProxyResolverMojo);
121 class ProxyResolverMojo::Job : public interfaces::ProxyResolverRequestClient {
122 public:
123 Job(ProxyResolverMojo* resolver,
124 const GURL& url,
125 ProxyInfo* results,
126 const CompletionCallback& callback);
127 ~Job() override;
129 // Cancels the job and prevents the callback from being run.
130 void Cancel();
132 // Returns the LoadState of this job.
133 LoadState load_state() { return LOAD_STATE_RESOLVING_PROXY_FOR_URL; }
135 private:
136 // Mojo error handler.
137 void OnConnectionError();
139 // Overridden from interfaces::ProxyResolverRequestClient:
140 void ReportResult(
141 int32_t error,
142 mojo::Array<interfaces::ProxyServerPtr> proxy_servers) override;
144 ProxyResolverMojo* resolver_;
145 const GURL url_;
146 ProxyInfo* results_;
147 CompletionCallback callback_;
149 base::ThreadChecker thread_checker_;
150 mojo::Binding<interfaces::ProxyResolverRequestClient> binding_;
153 ProxyResolverMojo::Job::Job(ProxyResolverMojo* resolver,
154 const GURL& url,
155 ProxyInfo* results,
156 const CompletionCallback& callback)
157 : resolver_(resolver),
158 url_(url),
159 results_(results),
160 callback_(callback),
161 binding_(this) {
162 binding_.set_connection_error_handler(base::Bind(
163 &ProxyResolverMojo::Job::OnConnectionError, base::Unretained(this)));
165 interfaces::ProxyResolverRequestClientPtr client_ptr;
166 binding_.Bind(mojo::GetProxy(&client_ptr));
167 resolver_->mojo_proxy_resolver_ptr_->GetProxyForUrl(mojo::String::From(url_),
168 client_ptr.Pass());
171 ProxyResolverMojo::Job::~Job() {
172 DCHECK(thread_checker_.CalledOnValidThread());
173 if (!callback_.is_null())
174 callback_.Run(ERR_PAC_SCRIPT_TERMINATED);
177 void ProxyResolverMojo::Job::Cancel() {
178 DCHECK(thread_checker_.CalledOnValidThread());
179 DCHECK(!callback_.is_null());
180 callback_.Reset();
183 void ProxyResolverMojo::Job::OnConnectionError() {
184 DCHECK(thread_checker_.CalledOnValidThread());
185 DVLOG(1) << "ProxyResolverMojo::Job::OnConnectionError";
186 resolver_->RemoveJob(this);
189 void ProxyResolverMojo::Job::ReportResult(
190 int32_t error,
191 mojo::Array<interfaces::ProxyServerPtr> proxy_servers) {
192 DCHECK(thread_checker_.CalledOnValidThread());
193 DVLOG(1) << "ProxyResolverMojo::Job::ReportResult: " << error;
195 if (error == OK) {
196 *results_ = proxy_servers.To<ProxyInfo>();
197 DVLOG(1) << "Servers: " << results_->ToPacString();
200 CompletionCallback callback = callback_;
201 callback_.Reset();
202 resolver_->RemoveJob(this);
203 callback.Run(error);
206 ProxyResolverMojo::ProxyResolverMojo(
207 interfaces::ProxyResolverPtr resolver_ptr,
208 scoped_ptr<interfaces::HostResolver> host_resolver,
209 scoped_ptr<mojo::Binding<interfaces::HostResolver>> host_resolver_binding,
210 scoped_ptr<base::ScopedClosureRunner> on_delete_callback_runner,
211 scoped_ptr<ErrorObserverHolder> error_observer)
212 : mojo_proxy_resolver_ptr_(resolver_ptr.Pass()),
213 mojo_host_resolver_(host_resolver.Pass()),
214 mojo_host_resolver_binding_(host_resolver_binding.Pass()),
215 error_observer_(error_observer.Pass()),
216 on_delete_callback_runner_(on_delete_callback_runner.Pass()) {
217 mojo_proxy_resolver_ptr_.set_connection_error_handler(base::Bind(
218 &ProxyResolverMojo::OnConnectionError, base::Unretained(this)));
221 ProxyResolverMojo::~ProxyResolverMojo() {
222 DCHECK(thread_checker_.CalledOnValidThread());
223 // All pending requests should have been cancelled.
224 DCHECK(pending_jobs_.empty());
227 void ProxyResolverMojo::OnConnectionError() {
228 DCHECK(thread_checker_.CalledOnValidThread());
229 DVLOG(1) << "ProxyResolverMojo::OnConnectionError";
231 // Disconnect from the Mojo proxy resolver service.
232 mojo_proxy_resolver_ptr_.reset();
235 void ProxyResolverMojo::RemoveJob(Job* job) {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 size_t num_erased = pending_jobs_.erase(job);
238 DCHECK(num_erased);
239 delete job;
242 int ProxyResolverMojo::GetProxyForURL(const GURL& url,
243 ProxyInfo* results,
244 const CompletionCallback& callback,
245 RequestHandle* request,
246 const BoundNetLog& net_log) {
247 DCHECK(thread_checker_.CalledOnValidThread());
249 if (!mojo_proxy_resolver_ptr_)
250 return ERR_PAC_SCRIPT_TERMINATED;
252 Job* job = new Job(this, url, results, callback);
253 bool inserted = pending_jobs_.insert(job).second;
254 DCHECK(inserted);
255 *request = job;
257 return ERR_IO_PENDING;
260 void ProxyResolverMojo::CancelRequest(RequestHandle request) {
261 DCHECK(thread_checker_.CalledOnValidThread());
262 Job* job = static_cast<Job*>(request);
263 DCHECK(job);
264 job->Cancel();
265 RemoveJob(job);
268 LoadState ProxyResolverMojo::GetLoadState(RequestHandle request) const {
269 Job* job = static_cast<Job*>(request);
270 CHECK_EQ(1u, pending_jobs_.count(job));
271 return job->load_state();
274 } // namespace
276 class ProxyResolverFactoryMojo::Job
277 : public interfaces::ProxyResolverFactoryRequestClient,
278 public ProxyResolverFactory::Request {
279 public:
280 Job(ProxyResolverFactoryMojo* factory,
281 const scoped_refptr<ProxyResolverScriptData>& pac_script,
282 scoped_ptr<ProxyResolver>* resolver,
283 const CompletionCallback& callback)
284 : factory_(factory),
285 resolver_(resolver),
286 callback_(callback),
287 binding_(this),
288 host_resolver_(new MojoHostResolverImpl(factory_->host_resolver_)),
289 host_resolver_binding_(
290 new mojo::Binding<interfaces::HostResolver>(host_resolver_.get())) {
291 interfaces::HostResolverPtr host_resolver_ptr;
292 interfaces::ProxyResolverFactoryRequestClientPtr client_ptr;
293 interfaces::ProxyResolverErrorObserverPtr error_observer_ptr;
294 binding_.Bind(mojo::GetProxy(&client_ptr));
295 if (!factory_->error_observer_factory_.is_null()) {
296 scoped_ptr<ProxyResolverErrorObserver> error_observer =
297 factory_->error_observer_factory_.Run();
298 if (error_observer) {
299 error_observer_.reset(new ErrorObserverHolder(
300 error_observer.Pass(), mojo::GetProxy(&error_observer_ptr)));
303 host_resolver_binding_->Bind(mojo::GetProxy(&host_resolver_ptr));
304 on_delete_callback_runner_ = factory_->mojo_proxy_factory_->CreateResolver(
305 mojo::String::From(pac_script->utf16()), mojo::GetProxy(&resolver_ptr_),
306 host_resolver_ptr.Pass(), error_observer_ptr.Pass(), client_ptr.Pass());
307 resolver_ptr_.set_connection_error_handler(
308 base::Bind(&ProxyResolverFactoryMojo::Job::OnConnectionError,
309 base::Unretained(this)));
310 binding_.set_connection_error_handler(
311 base::Bind(&ProxyResolverFactoryMojo::Job::OnConnectionError,
312 base::Unretained(this)));
315 void OnConnectionError() { ReportResult(ERR_PAC_SCRIPT_TERMINATED); }
317 private:
318 void ReportResult(int32_t error) override {
319 resolver_ptr_.set_connection_error_handler(mojo::Closure());
320 binding_.set_connection_error_handler(mojo::Closure());
321 if (error == OK) {
322 resolver_->reset(new ProxyResolverMojo(
323 resolver_ptr_.Pass(), host_resolver_.Pass(),
324 host_resolver_binding_.Pass(), on_delete_callback_runner_.Pass(),
325 error_observer_.Pass()));
327 on_delete_callback_runner_.reset();
328 callback_.Run(error);
331 ProxyResolverFactoryMojo* const factory_;
332 scoped_ptr<ProxyResolver>* resolver_;
333 const CompletionCallback callback_;
334 interfaces::ProxyResolverPtr resolver_ptr_;
335 mojo::Binding<interfaces::ProxyResolverFactoryRequestClient> binding_;
336 scoped_ptr<interfaces::HostResolver> host_resolver_;
337 scoped_ptr<mojo::Binding<interfaces::HostResolver>> host_resolver_binding_;
338 scoped_ptr<base::ScopedClosureRunner> on_delete_callback_runner_;
339 scoped_ptr<ErrorObserverHolder> error_observer_;
342 ProxyResolverFactoryMojo::ProxyResolverFactoryMojo(
343 MojoProxyResolverFactory* mojo_proxy_factory,
344 HostResolver* host_resolver,
345 const base::Callback<scoped_ptr<ProxyResolverErrorObserver>()>&
346 error_observer_factory)
347 : ProxyResolverFactory(true),
348 mojo_proxy_factory_(mojo_proxy_factory),
349 host_resolver_(host_resolver),
350 error_observer_factory_(error_observer_factory) {
353 ProxyResolverFactoryMojo::~ProxyResolverFactoryMojo() = default;
355 int ProxyResolverFactoryMojo::CreateProxyResolver(
356 const scoped_refptr<ProxyResolverScriptData>& pac_script,
357 scoped_ptr<ProxyResolver>* resolver,
358 const CompletionCallback& callback,
359 scoped_ptr<ProxyResolverFactory::Request>* request) {
360 DCHECK(resolver);
361 DCHECK(request);
362 if (pac_script->type() != ProxyResolverScriptData::TYPE_SCRIPT_CONTENTS ||
363 pac_script->utf16().empty()) {
364 return ERR_PAC_SCRIPT_FAILED;
366 request->reset(new Job(this, pac_script, resolver, callback));
367 return ERR_IO_PENDING;
370 } // namespace net