Roll src/third_party/WebKit d26421b:4b1dbe3 (svn 194839:194840)
[chromium-blink-merge.git] / net / proxy / proxy_resolver_mojo.cc
blobbc15704d7194268205b39b6130be8be56d1ada02
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 CompletionCallback callback = callback_;
104 callback_.Reset();
105 resolver_->RemoveJob(this);
106 callback.Run(error);
109 void ProxyResolverMojo::Job::LoadStateChanged(int32_t load_state) {
110 load_state_ = static_cast<LoadState>(load_state);
113 ProxyResolverMojo::ProxyResolverMojo(
114 MojoProxyResolverFactory* mojo_proxy_resolver_factory,
115 HostResolver* host_resolver)
116 : ProxyResolver(true /* |expects_pac_bytes| */),
117 mojo_proxy_resolver_factory_(mojo_proxy_resolver_factory),
118 host_resolver_(host_resolver) {
121 ProxyResolverMojo::~ProxyResolverMojo() {
122 DCHECK(thread_checker_.CalledOnValidThread());
123 // All pending requests should have been cancelled.
124 DCHECK(pending_jobs_.empty());
125 DCHECK(set_pac_script_callback_.IsCancelled());
128 void ProxyResolverMojo::CancelSetPacScript() {
129 DCHECK(thread_checker_.CalledOnValidThread());
130 set_pac_script_callback_.Cancel();
133 int ProxyResolverMojo::SetPacScript(
134 const scoped_refptr<ProxyResolverScriptData>& pac_script,
135 const CompletionCallback& callback) {
136 DCHECK(thread_checker_.CalledOnValidThread());
137 DCHECK(set_pac_script_callback_.IsCancelled());
138 DCHECK(!callback.is_null());
139 if (pac_script->type() != ProxyResolverScriptData::TYPE_SCRIPT_CONTENTS ||
140 pac_script->utf16().empty()) {
141 return ERR_PAC_SCRIPT_FAILED;
144 DVLOG(1) << "ProxyResolverMojo::SetPacScript: " << pac_script->utf16();
145 set_pac_script_callback_.Reset(
146 base::Bind(&ProxyResolverMojo::OnSetPacScriptDone, base::Unretained(this),
147 pac_script, callback));
149 if (!mojo_proxy_resolver_ptr_)
150 SetUpServices();
152 mojo_proxy_resolver_ptr_->SetPacScript(
153 mojo::String::From(pac_script->utf16()),
154 set_pac_script_callback_.callback());
156 return ERR_IO_PENDING;
159 void ProxyResolverMojo::OnSetPacScriptDone(
160 const scoped_refptr<ProxyResolverScriptData>& pac_script,
161 const CompletionCallback& callback,
162 int32_t result) {
163 DCHECK(thread_checker_.CalledOnValidThread());
164 DCHECK(!set_pac_script_callback_.IsCancelled());
165 DVLOG(1) << "ProxyResolverMojo::OnSetPacScriptDone: " << result;
167 // |callback| is owned by |set_pac_script_callback_|, so make a copy before
168 // cancelling.
169 auto callback_copy = callback;
170 set_pac_script_callback_.Cancel();
171 callback_copy.Run(result);
174 void ProxyResolverMojo::SetUpServices() {
175 DCHECK(thread_checker_.CalledOnValidThread());
176 // A Mojo service implementation must outlive its binding.
177 mojo_host_resolver_binding_.reset();
179 interfaces::HostResolverPtr mojo_host_resolver_ptr;
180 mojo_host_resolver_.reset(new MojoHostResolverImpl(host_resolver_));
181 mojo_host_resolver_binding_.reset(new mojo::Binding<interfaces::HostResolver>(
182 mojo_host_resolver_.get(), mojo::GetProxy(&mojo_host_resolver_ptr)));
183 mojo_proxy_resolver_ptr_.reset();
184 mojo_proxy_resolver_factory_->Create(
185 mojo::GetProxy(&mojo_proxy_resolver_ptr_), mojo_host_resolver_ptr.Pass());
186 mojo_proxy_resolver_ptr_.set_error_handler(this);
189 void ProxyResolverMojo::OnConnectionError() {
190 DCHECK(thread_checker_.CalledOnValidThread());
191 DVLOG(1) << "ProxyResolverMojo::OnConnectionError";
193 // Disconnect from the Mojo proxy resolver service. An attempt to reconnect
194 // will happen on the next |SetPacScript()| request.
195 mojo_proxy_resolver_ptr_.reset();
197 // This callback may call |SetPacScript()| and re-create the connection. So
198 // disconnect from the Mojo service (above) before aborting the pending
199 // request.
200 if (!set_pac_script_callback_.IsCancelled())
201 set_pac_script_callback_.callback().Run(ERR_PAC_SCRIPT_TERMINATED);
204 void ProxyResolverMojo::RemoveJob(Job* job) {
205 DCHECK(thread_checker_.CalledOnValidThread());
206 size_t num_erased = pending_jobs_.erase(job);
207 DCHECK(num_erased);
208 delete job;
211 int ProxyResolverMojo::GetProxyForURL(const GURL& url,
212 ProxyInfo* results,
213 const CompletionCallback& callback,
214 RequestHandle* request,
215 const BoundNetLog& net_log) {
216 DCHECK(thread_checker_.CalledOnValidThread());
218 // If the Mojo service is not connected, fail. The Mojo service is connected
219 // when the script is set, which must be done after construction and after a
220 // previous request returns ERR_PAC_SCRIPT_TERMINATED due to the Mojo proxy
221 // resolver process crashing.
222 if (!mojo_proxy_resolver_ptr_) {
223 DVLOG(1) << "ProxyResolverMojo::GetProxyForURL: Mojo not connected";
224 return ERR_PAC_SCRIPT_TERMINATED;
227 Job* job = new Job(this, url, results, callback);
228 bool inserted = pending_jobs_.insert(job).second;
229 DCHECK(inserted);
230 *request = job;
232 return ERR_IO_PENDING;
235 void ProxyResolverMojo::CancelRequest(RequestHandle request) {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 Job* job = static_cast<Job*>(request);
238 DCHECK(job);
239 job->Cancel();
240 RemoveJob(job);
243 LoadState ProxyResolverMojo::GetLoadState(RequestHandle request) const {
244 Job* job = static_cast<Job*>(request);
245 CHECK_EQ(1u, pending_jobs_.count(job));
246 return job->load_state();
249 } // namespace net