proxy_resolver_factory_mojo.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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.
  4. #include "services/network/proxy_resolver_factory_mojo.h"
  5. #include <set>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/logging.h"
  12. #include "base/memory/raw_ptr.h"
  13. #include "base/sequence_checker.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "base/task/task_runner.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/values.h"
  18. #include "mojo/public/cpp/bindings/pending_remote.h"
  19. #include "mojo/public/cpp/bindings/receiver.h"
  20. #include "mojo/public/cpp/bindings/remote.h"
  21. #include "net/base/ip_address.h"
  22. #include "net/base/load_states.h"
  23. #include "net/base/net_errors.h"
  24. #include "net/base/network_isolation_key.h"
  25. #include "net/log/net_log.h"
  26. #include "net/log/net_log_capture_mode.h"
  27. #include "net/log/net_log_event_type.h"
  28. #include "net/log/net_log_with_source.h"
  29. #include "net/proxy_resolution/pac_file_data.h"
  30. #include "net/proxy_resolution/proxy_info.h"
  31. #include "net/proxy_resolution/proxy_resolve_dns_operation.h"
  32. #include "net/proxy_resolution/proxy_resolver.h"
  33. #include "net/proxy_resolution/proxy_resolver_error_observer.h"
  34. #include "services/network/mojo_host_resolver_impl.h"
  35. #include "services/network/proxy_auto_config_library.h"
  36. #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
  37. namespace net {
  38. class NetworkIsolationKey;
  39. }
  40. namespace network {
  41. namespace {
  42. base::Value NetLogErrorParams(int line_number, const std::string& message) {
  43. base::Value::Dict dict;
  44. dict.Set("line_number", line_number);
  45. dict.Set("message", message);
  46. return base::Value(std::move(dict));
  47. }
  48. // Implementation for myIpAddress() and myIpAddressEx() that is expected to run
  49. // on a worker thread. Will notify |client| on completion.
  50. void DoMyIpAddressOnWorker(
  51. bool is_ex,
  52. mojo::PendingRemote<proxy_resolver::mojom::HostResolverRequestClient>
  53. client_remote) {
  54. // Resolve the list of IP addresses.
  55. std::vector<net::IPAddress> my_ip_addresses =
  56. is_ex ? PacMyIpAddressEx() : PacMyIpAddress();
  57. mojo::Remote<proxy_resolver::mojom::HostResolverRequestClient> client(
  58. std::move(client_remote));
  59. // TODO(eroman): Note that this code always returns a success response (with
  60. // loopback) rather than passing forward the error. This is to ensure that the
  61. // response gets cached on the proxy resolver process side, since this layer
  62. // here does not currently do any caching or de-duplication. This should be
  63. // cleaned up once the interfaces are refactored. Lastly note that for
  64. // myIpAddress() this doesn't change the final result. However for
  65. // myIpAddressEx() it means we return 127.0.0.1 rather than empty string.
  66. if (my_ip_addresses.empty())
  67. my_ip_addresses.push_back(net::IPAddress::IPv4Localhost());
  68. client->ReportResult(net::OK, my_ip_addresses);
  69. }
  70. // A mixin that forwards logging to (Bound)NetLog and ProxyResolverErrorObserver
  71. // and DNS requests to a MojoHostResolverImpl, which is implemented in terms of
  72. // a HostResolver, or myIpAddress[Ex]() which is implemented by //net.
  73. template <typename ClientInterface>
  74. class ClientMixin : public ClientInterface {
  75. public:
  76. ClientMixin(net::HostResolver* host_resolver,
  77. net::ProxyResolverErrorObserver* error_observer,
  78. net::NetLog* net_log,
  79. const net::NetLogWithSource& net_log_with_source)
  80. : host_resolver_(host_resolver, net_log_with_source),
  81. error_observer_(error_observer),
  82. net_log_(net_log),
  83. net_log_with_source_(net_log_with_source) {}
  84. // Overridden from ClientInterface:
  85. void Alert(const std::string& message) override {
  86. net_log_with_source_.AddEventWithStringParams(
  87. net::NetLogEventType::PAC_JAVASCRIPT_ALERT, "message", message);
  88. if (net_log_)
  89. net_log_->AddGlobalEntryWithStringParams(
  90. net::NetLogEventType::PAC_JAVASCRIPT_ALERT, "message", message);
  91. }
  92. void OnError(int32_t line_number, const std::string& message) override {
  93. net_log_with_source_.AddEvent(
  94. net::NetLogEventType::PAC_JAVASCRIPT_ERROR,
  95. [&] { return NetLogErrorParams(line_number, message); });
  96. if (net_log_)
  97. net_log_->AddGlobalEntry(net::NetLogEventType::PAC_JAVASCRIPT_ERROR, [&] {
  98. return NetLogErrorParams(line_number, message);
  99. });
  100. if (error_observer_) {
  101. error_observer_->OnPACScriptError(line_number,
  102. base::UTF8ToUTF16(message));
  103. }
  104. }
  105. // TODO(eroman): Split the client interfaces so ResolveDns() does not also
  106. // carry the myIpAddress(Ex) requests.
  107. void ResolveDns(
  108. const std::string& hostname,
  109. net::ProxyResolveDnsOperation operation,
  110. const net::NetworkIsolationKey& network_isolation_key,
  111. mojo::PendingRemote<proxy_resolver::mojom::HostResolverRequestClient>
  112. client) override {
  113. bool is_ex = operation == net::ProxyResolveDnsOperation::DNS_RESOLVE_EX ||
  114. operation == net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX;
  115. if (operation == net::ProxyResolveDnsOperation::MY_IP_ADDRESS ||
  116. operation == net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX) {
  117. GetMyIpAddressTaskRuner()->PostTask(
  118. FROM_HERE,
  119. base::BindOnce(&DoMyIpAddressOnWorker, is_ex, std::move(client)));
  120. } else {
  121. // Request was for dnsResolve() or dnsResolveEx().
  122. host_resolver_.Resolve(hostname, network_isolation_key, is_ex,
  123. std::move(client));
  124. }
  125. }
  126. protected:
  127. // TODO(eroman): This doesn't track being blocked in myIpAddress(Ex) handler.
  128. bool dns_request_in_progress() {
  129. return host_resolver_.request_in_progress();
  130. }
  131. // Returns a task runner used to run the code for myIpAddress[Ex].
  132. static scoped_refptr<base::TaskRunner> GetMyIpAddressTaskRuner() {
  133. // TODO(eroman): While these tasks are expected to normally run quickly,
  134. // it would be prudent to enforce a bound on outstanding tasks, and maybe
  135. // de-duplication of requests.
  136. //
  137. // However the better place to focus on is de-duplication and caching on the
  138. // proxy service side (which currently caches but doesn't de-duplicate).
  139. return base::ThreadPool::CreateSequencedTaskRunner(
  140. {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
  141. base::TaskPriority::USER_VISIBLE});
  142. }
  143. private:
  144. MojoHostResolverImpl host_resolver_;
  145. const raw_ptr<net::ProxyResolverErrorObserver> error_observer_;
  146. const raw_ptr<net::NetLog> net_log_;
  147. const net::NetLogWithSource net_log_with_source_;
  148. };
  149. // Implementation of ProxyResolver that connects to a Mojo service to evaluate
  150. // PAC scripts. This implementation only knows about Mojo services, and
  151. // therefore that service may live in or out of process.
  152. //
  153. // This implementation reports disconnections from the Mojo service (i.e. if the
  154. // service is out-of-process and that process crashes) using the error code
  155. // ERR_PAC_SCRIPT_TERMINATED.
  156. class ProxyResolverMojo : public net::ProxyResolver {
  157. public:
  158. // Constructs a ProxyResolverMojo that connects to a mojo proxy resolver
  159. // implementation using |resolver_remote|. The implementation uses
  160. // |host_resolver| as the DNS resolver, using |host_resolver_binding| to
  161. // communicate with it.
  162. ProxyResolverMojo(
  163. mojo::PendingRemote<proxy_resolver::mojom::ProxyResolver> resolver_remote,
  164. net::HostResolver* host_resolver,
  165. std::unique_ptr<net::ProxyResolverErrorObserver> error_observer,
  166. net::NetLog* net_log);
  167. ProxyResolverMojo(const ProxyResolverMojo&) = delete;
  168. ProxyResolverMojo& operator=(const ProxyResolverMojo&) = delete;
  169. ~ProxyResolverMojo() override;
  170. // ProxyResolver implementation:
  171. int GetProxyForURL(const GURL& url,
  172. const net::NetworkIsolationKey& network_isolation_key,
  173. net::ProxyInfo* results,
  174. net::CompletionOnceCallback callback,
  175. std::unique_ptr<Request>* request,
  176. const net::NetLogWithSource& net_log) override;
  177. private:
  178. class Job;
  179. SEQUENCE_CHECKER(sequence_checker_);
  180. // Mojo disconnect handler.
  181. void OnMojoDisconnect();
  182. // Connection to the Mojo proxy resolver.
  183. mojo::Remote<proxy_resolver::mojom::ProxyResolver>
  184. mojo_proxy_resolver_remote_;
  185. raw_ptr<net::HostResolver> host_resolver_;
  186. std::unique_ptr<net::ProxyResolverErrorObserver> error_observer_;
  187. raw_ptr<net::NetLog> net_log_;
  188. };
  189. class ProxyResolverMojo::Job
  190. : public ProxyResolver::Request,
  191. public ClientMixin<proxy_resolver::mojom::ProxyResolverRequestClient> {
  192. public:
  193. Job(ProxyResolverMojo* resolver,
  194. const GURL& url,
  195. const net::NetworkIsolationKey& network_isolation_key,
  196. net::ProxyInfo* results,
  197. net::CompletionOnceCallback callback,
  198. const net::NetLogWithSource& net_log);
  199. Job(const Job&) = delete;
  200. Job& operator=(const Job&) = delete;
  201. ~Job() override;
  202. // Returns the LoadState of this job.
  203. net::LoadState GetLoadState() override;
  204. private:
  205. // Mojo disconnection handler.
  206. void OnMojoDisconnect();
  207. // Overridden from proxy_resolver::mojom::ProxyResolverRequestClient:
  208. void ReportResult(int32_t error, const net::ProxyInfo& proxy_info) override;
  209. // Completes a request with a result code.
  210. void CompleteRequest(int result);
  211. const GURL url_;
  212. raw_ptr<net::ProxyInfo> results_;
  213. net::CompletionOnceCallback callback_;
  214. SEQUENCE_CHECKER(sequence_checker_);
  215. mojo::Receiver<proxy_resolver::mojom::ProxyResolverRequestClient> receiver_{
  216. this};
  217. };
  218. ProxyResolverMojo::Job::Job(
  219. ProxyResolverMojo* resolver,
  220. const GURL& url,
  221. const net::NetworkIsolationKey& network_isolation_key,
  222. net::ProxyInfo* results,
  223. net::CompletionOnceCallback callback,
  224. const net::NetLogWithSource& net_log)
  225. : ClientMixin<proxy_resolver::mojom::ProxyResolverRequestClient>(
  226. resolver->host_resolver_,
  227. resolver->error_observer_.get(),
  228. resolver->net_log_,
  229. net_log),
  230. url_(url),
  231. results_(results),
  232. callback_(std::move(callback)) {
  233. resolver->mojo_proxy_resolver_remote_->GetProxyForUrl(
  234. url_, network_isolation_key, receiver_.BindNewPipeAndPassRemote());
  235. receiver_.set_disconnect_handler(base::BindOnce(
  236. &ProxyResolverMojo::Job::OnMojoDisconnect, base::Unretained(this)));
  237. }
  238. ProxyResolverMojo::Job::~Job() {}
  239. net::LoadState ProxyResolverMojo::Job::GetLoadState() {
  240. return dns_request_in_progress() ? net::LOAD_STATE_RESOLVING_HOST_IN_PAC_FILE
  241. : net::LOAD_STATE_RESOLVING_PROXY_FOR_URL;
  242. }
  243. void ProxyResolverMojo::Job::OnMojoDisconnect() {
  244. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  245. DVLOG(1) << "ProxyResolverMojo::Job::OnMojoDisconnect";
  246. CompleteRequest(net::ERR_PAC_SCRIPT_TERMINATED);
  247. }
  248. void ProxyResolverMojo::Job::CompleteRequest(int result) {
  249. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  250. net::CompletionOnceCallback callback = std::move(callback_);
  251. receiver_.reset();
  252. std::move(callback).Run(result);
  253. }
  254. void ProxyResolverMojo::Job::ReportResult(int32_t error,
  255. const net::ProxyInfo& proxy_info) {
  256. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  257. DVLOG(1) << "ProxyResolverMojo::Job::ReportResult: " << error;
  258. if (error == net::OK) {
  259. *results_ = proxy_info;
  260. DVLOG(1) << "Servers: " << results_->ToPacString();
  261. }
  262. CompleteRequest(error);
  263. }
  264. ProxyResolverMojo::ProxyResolverMojo(
  265. mojo::PendingRemote<proxy_resolver::mojom::ProxyResolver> resolver_remote,
  266. net::HostResolver* host_resolver,
  267. std::unique_ptr<net::ProxyResolverErrorObserver> error_observer,
  268. net::NetLog* net_log)
  269. : mojo_proxy_resolver_remote_(std::move(resolver_remote)),
  270. host_resolver_(host_resolver),
  271. error_observer_(std::move(error_observer)),
  272. net_log_(net_log) {
  273. mojo_proxy_resolver_remote_.set_disconnect_handler(base::BindOnce(
  274. &ProxyResolverMojo::OnMojoDisconnect, base::Unretained(this)));
  275. }
  276. ProxyResolverMojo::~ProxyResolverMojo() {
  277. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  278. }
  279. void ProxyResolverMojo::OnMojoDisconnect() {
  280. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  281. DVLOG(1) << "ProxyResolverMojo::OnMojoDisconnect";
  282. // Disconnect from the Mojo proxy resolver service.
  283. mojo_proxy_resolver_remote_.reset();
  284. }
  285. int ProxyResolverMojo::GetProxyForURL(
  286. const GURL& url,
  287. const net::NetworkIsolationKey& network_isolation_key,
  288. net::ProxyInfo* results,
  289. net::CompletionOnceCallback callback,
  290. std::unique_ptr<Request>* request,
  291. const net::NetLogWithSource& net_log) {
  292. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  293. if (!mojo_proxy_resolver_remote_)
  294. return net::ERR_PAC_SCRIPT_TERMINATED;
  295. *request = std::make_unique<Job>(this, url, network_isolation_key, results,
  296. std::move(callback), net_log);
  297. return net::ERR_IO_PENDING;
  298. }
  299. } // namespace
  300. // A Job to create a ProxyResolver instance.
  301. //
  302. // Note: a Job instance is not tied to a particular resolve request, and hence
  303. // there is no per-request logging to be done (any netlog events are only sent
  304. // globally) so this always uses an empty NetLogWithSource.
  305. class ProxyResolverFactoryMojo::Job
  306. : public ClientMixin<
  307. proxy_resolver::mojom::ProxyResolverFactoryRequestClient>,
  308. public ProxyResolverFactory::Request {
  309. public:
  310. Job(ProxyResolverFactoryMojo* factory,
  311. const scoped_refptr<net::PacFileData>& pac_script,
  312. std::unique_ptr<net::ProxyResolver>* resolver,
  313. net::CompletionOnceCallback callback,
  314. std::unique_ptr<net::ProxyResolverErrorObserver> error_observer)
  315. : ClientMixin<proxy_resolver::mojom::ProxyResolverFactoryRequestClient>(
  316. factory->host_resolver_,
  317. error_observer.get(),
  318. factory->net_log_,
  319. net::NetLogWithSource()),
  320. factory_(factory),
  321. resolver_(resolver),
  322. callback_(std::move(callback)),
  323. error_observer_(std::move(error_observer)) {
  324. factory_->mojo_proxy_factory_->CreateResolver(
  325. base::UTF16ToUTF8(pac_script->utf16()),
  326. resolver_remote_.InitWithNewPipeAndPassReceiver(),
  327. receiver_.BindNewPipeAndPassRemote());
  328. receiver_.set_disconnect_handler(
  329. base::BindOnce(&ProxyResolverFactoryMojo::Job::OnMojoDisconnect,
  330. base::Unretained(this)));
  331. }
  332. void OnMojoDisconnect() { ReportResult(net::ERR_PAC_SCRIPT_TERMINATED); }
  333. private:
  334. void ReportResult(int32_t error) override {
  335. // Prevent any other messages arriving unexpectedly, in the case |this|
  336. // isn't destroyed immediately.
  337. receiver_.reset();
  338. if (error == net::OK) {
  339. *resolver_ = std::make_unique<ProxyResolverMojo>(
  340. std::move(resolver_remote_), factory_->host_resolver_,
  341. std::move(error_observer_), factory_->net_log_);
  342. }
  343. std::move(callback_).Run(error);
  344. }
  345. const raw_ptr<ProxyResolverFactoryMojo> factory_;
  346. raw_ptr<std::unique_ptr<net::ProxyResolver>> resolver_;
  347. net::CompletionOnceCallback callback_;
  348. mojo::PendingRemote<proxy_resolver::mojom::ProxyResolver> resolver_remote_;
  349. mojo::Receiver<proxy_resolver::mojom::ProxyResolverFactoryRequestClient>
  350. receiver_{this};
  351. std::unique_ptr<net::ProxyResolverErrorObserver> error_observer_;
  352. };
  353. ProxyResolverFactoryMojo::ProxyResolverFactoryMojo(
  354. mojo::PendingRemote<proxy_resolver::mojom::ProxyResolverFactory>
  355. mojo_proxy_factory,
  356. net::HostResolver* host_resolver,
  357. const base::RepeatingCallback<
  358. std::unique_ptr<net::ProxyResolverErrorObserver>()>&
  359. error_observer_factory,
  360. net::NetLog* net_log)
  361. : ProxyResolverFactory(true),
  362. mojo_proxy_factory_(std::move(mojo_proxy_factory)),
  363. host_resolver_(host_resolver),
  364. error_observer_factory_(error_observer_factory),
  365. net_log_(net_log) {}
  366. ProxyResolverFactoryMojo::~ProxyResolverFactoryMojo() = default;
  367. int ProxyResolverFactoryMojo::CreateProxyResolver(
  368. const scoped_refptr<net::PacFileData>& pac_script,
  369. std::unique_ptr<net::ProxyResolver>* resolver,
  370. net::CompletionOnceCallback callback,
  371. std::unique_ptr<net::ProxyResolverFactory::Request>* request) {
  372. DCHECK(resolver);
  373. DCHECK(request);
  374. if (pac_script->type() != net::PacFileData::TYPE_SCRIPT_CONTENTS ||
  375. pac_script->utf16().empty()) {
  376. return net::ERR_PAC_SCRIPT_FAILED;
  377. }
  378. *request = std::make_unique<Job>(
  379. this, pac_script, resolver, std::move(callback),
  380. error_observer_factory_.is_null() ? nullptr
  381. : error_observer_factory_.Run());
  382. return net::ERR_IO_PENDING;
  383. }
  384. } // namespace network