1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "services/proxy_resolver/host_resolver_mojo.h"
11 #include "base/check.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "mojo/public/cpp/bindings/receiver.h"
17 #include "net/base/completion_once_callback.h"
18 #include "net/base/ip_address.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/network_anonymization_key.h"
21 #include "net/dns/public/dns_query_type.h"
22 #include "net/dns/public/host_resolver_source.h"
23 #include "net/proxy_resolution/proxy_resolve_dns_operation.h"
24 #include "services/proxy_resolver/proxy_host_resolver_cache.h"
26 namespace proxy_resolver {
30 bool IsExOperation(net::ProxyResolveDnsOperation operation) {
31 return operation == net::ProxyResolveDnsOperation::DNS_RESOLVE_EX ||
32 operation == net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX;
37 class HostResolverMojo::RequestImpl : public ProxyHostResolver::Request,
38 public mojom::HostResolverRequestClient {
40 RequestImpl(const std::string& hostname,
41 net::ProxyResolveDnsOperation operation,
42 const net::NetworkAnonymizationKey& network_anonymization_key,
43 base::WeakPtr<ProxyHostResolverCache> host_cache,
45 : hostname_(hostname),
46 operation_(operation),
47 network_anonymization_key_(network_anonymization_key),
48 host_cache_(std::move(host_cache)),
51 ~RequestImpl() override = default;
53 // ProxyHostResolver::Request override
54 int Start(net::CompletionOnceCallback callback) override {
55 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
56 DVLOG(1) << "Resolve " << hostname_;
58 // Get from a local cache if able. Even though the network process does its
59 // own HostResolver caching, that would still require an async mojo call.
60 // Async returns are particularly expensive here, so the local cache
61 // maximizes ability to return synchronously.
63 // TODO(ericorth@chromium.org): Consider some small refactors to allow
64 // direct non-mojo access to the fast, synchronous, and self-contained logic
65 // from net::HostResolver (e.g. IP-literal and "localhost" resolution). That
66 // could allow reducing async returns even further.
68 const std::vector<net::IPAddress>* cached_result = host_cache_->LookupEntry(
69 hostname_, network_anonymization_key_, IsExOperation(operation_));
71 results_ = *cached_result;
72 DVLOG(1) << "Resolved " << hostname_ << " from cache";
76 callback_ = std::move(callback);
77 impl_->ResolveDns(hostname_, operation_, network_anonymization_key_,
78 receiver_.BindNewPipeAndPassRemote());
79 receiver_.set_disconnect_handler(
80 base::BindOnce(&RequestImpl::OnDisconnect, base::Unretained(this)));
81 return net::ERR_IO_PENDING;
84 const std::vector<net::IPAddress>& GetResults() const override {
88 // mojom::HostResolverRequestClient override
89 void ReportResult(int32_t error,
90 const std::vector<net::IPAddress>& result) override {
91 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
93 if (error == net::OK) {
96 host_cache_->StoreEntry(hostname_, network_anonymization_key_,
97 IsExOperation(operation_), result);
101 std::move(callback_).Run(error);
105 void OnDisconnect() { ReportResult(net::ERR_FAILED, {} /* result */); }
107 const std::string hostname_;
108 const net::ProxyResolveDnsOperation operation_;
109 const net::NetworkAnonymizationKey network_anonymization_key_;
111 mojo::Receiver<mojom::HostResolverRequestClient> receiver_{this};
112 net::CompletionOnceCallback callback_;
114 base::WeakPtr<ProxyHostResolverCache> host_cache_;
115 const raw_ptr<Impl> impl_;
116 std::vector<net::IPAddress> results_;
118 THREAD_CHECKER(thread_checker_);
121 HostResolverMojo::HostResolverMojo(Impl* impl) : impl_(impl) {}
123 HostResolverMojo::~HostResolverMojo() = default;
125 std::unique_ptr<ProxyHostResolver::Request> HostResolverMojo::CreateRequest(
126 const std::string& hostname,
127 net::ProxyResolveDnsOperation operation,
128 const net::NetworkAnonymizationKey& network_anonymization_key) {
129 DCHECK(thread_checker_.CalledOnValidThread());
130 return std::make_unique<RequestImpl>(
131 hostname, operation, network_anonymization_key,
132 host_cache_weak_factory_.GetWeakPtr(), impl_);
135 } // namespace proxy_resolver