Commit 59fa7f80 authored by Eric Orth's avatar Eric Orth Committed by Commit Bot

Add mojo version for new HostResolver API.

Implemented as a single ResolveHost method in NetworkContext for now with all
the real work in a separate ResolveHostRequest class that we'll be able to use
from multiple places if we copy or move the ResolveHost method to other
interfaces.

Per recent discussions, we've diverged from the design in the doc. Responses
are now always sent via a dedicated response client mojo pipe instead of using
response callbacks on the request pipe. This makes cancellation and callback
control much clearer and bug-proofed for clients because it's always clear
which pipe controls the callbacks and the callbacks are usually tightly bound
to the relevant mojo binding. The design doc will be updated after this CL is
landed.

Design doc:
https://docs.google.com/document/d/1NmADJX00oRe9TxFCJTWl8ofdfyR22pbKT8-5Ad5lBsU

Bug: 821021
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: Ib0ae407008fdbec089437083796cae725cd8d8d0
Reviewed-on: https://chromium-review.googlesource.com/1113665Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Commit-Queue: Eric Orth <ericorth@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580325}
parent 5da0d0d1
......@@ -74,6 +74,8 @@ component("network_service") {
"proxy_resolving_socket_factory_mojo.h",
"proxy_resolving_socket_mojo.cc",
"proxy_resolving_socket_mojo.h",
"resolve_host_request.cc",
"resolve_host_request.h",
"resource_scheduler.cc",
"resource_scheduler.h",
"resource_scheduler_client.cc",
......
......@@ -77,6 +77,7 @@
#include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/resolve_host_request.h"
#include "services/network/resource_scheduler_client.h"
#include "services/network/restricted_cookie_manager.h"
#include "services/network/session_cleanup_channel_id_store.h"
......@@ -517,6 +518,10 @@ void NetworkContext::DestroyURLLoaderFactory(
url_loader_factories_.erase(it);
}
size_t NetworkContext::GetNumOutstandingResolveHostRequestsForTesting() const {
return resolve_host_requests_.size();
}
void NetworkContext::ClearNetworkingHistorySince(
base::Time time,
base::OnceClosure completion_callback) {
......@@ -794,6 +799,26 @@ void NetworkContext::CreateNetLogExporter(
std::move(request));
}
void NetworkContext::ResolveHost(const net::HostPortPair& host,
mojom::ResolveHostHandleRequest control_handle,
mojom::ResolveHostClientPtr response_client) {
auto request = std::make_unique<ResolveHostRequest>(
url_request_context_->host_resolver(), host, network_service_->net_log());
int rv =
request->Start(std::move(control_handle), std::move(response_client),
base::BindOnce(&NetworkContext::OnResolveHostComplete,
base::Unretained(this), request.get()));
if (rv != net::ERR_IO_PENDING)
return;
// Store the request with the context so it can be cancelled on context
// shutdown.
bool insertion_result =
resolve_host_requests_.insert(std::move(request)).second;
DCHECK(insertion_result);
}
void NetworkContext::AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......@@ -1206,6 +1231,15 @@ void NetworkContext::OnHttpCacheCleared(ClearHttpCacheCallback callback,
std::move(callback).Run();
}
void NetworkContext::OnResolveHostComplete(ResolveHostRequest* request,
int error) {
DCHECK_NE(net::ERR_IO_PENDING, error);
auto found_request = resolve_host_requests_.find(request);
DCHECK(found_request != resolve_host_requests_.end());
resolve_host_requests_.erase(found_request);
}
void NetworkContext::OnHttpCacheSizeComputed(
ComputeHttpCacheSizeCallback callback,
HttpCacheDataCounter* counter,
......
......@@ -23,6 +23,7 @@
#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "services/network/http_cache_data_counter.h"
#include "services/network/http_cache_data_remover.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "services/network/public/mojom/proxy_resolving_socket.mojom.h"
......@@ -40,6 +41,7 @@ class UnguessableToken;
namespace net {
class CertVerifier;
class HostPortPair;
class ReportSender;
class StaticHttpUserAgentSettings;
class URLRequestContext;
......@@ -55,6 +57,7 @@ class CookieManager;
class ExpectCTReporter;
class NetworkService;
class ProxyLookupRequest;
class ResolveHostRequest;
class ResourceScheduler;
class ResourceSchedulerClient;
class URLRequestContextBuilderMojo;
......@@ -202,6 +205,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const GURL& url,
mojom::ProxyLookupClientPtr proxy_lookup_client) override;
void CreateNetLogExporter(mojom::NetLogExporterRequest request) override;
void ResolveHost(const net::HostPortPair& host,
mojom::ResolveHostHandleRequest control_handle,
mojom::ResolveHostClientPtr response_client) override;
void AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......@@ -225,6 +231,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// no open pipes.
void DestroyURLLoaderFactory(cors::CORSURLLoaderFactory* url_loader_factory);
size_t GetNumOutstandingResolveHostRequestsForTesting() const;
size_t pending_proxy_lookup_requests_for_testing() const {
return proxy_lookup_requests_.size();
}
......@@ -241,6 +249,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void OnHttpCacheCleared(ClearHttpCacheCallback callback,
HttpCacheDataRemover* remover);
void OnResolveHostComplete(ResolveHostRequest* request, int error);
// Invoked when the computation for ComputeHttpCacheSize() has been completed,
// to report result to user via |callback| and clean things up.
void OnHttpCacheSizeComputed(ComputeHttpCacheSizeCallback callback,
......@@ -323,6 +333,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
require_ct_delegate_;
std::unique_ptr<certificate_transparency::TreeStateTracker> ct_tree_tracker_;
std::set<std::unique_ptr<ResolveHostRequest>, base::UniquePtrComparator>
resolve_host_requests_;
DISALLOW_COPY_AND_ASSIGN(NetworkContext);
};
......
......@@ -79,6 +79,7 @@ mojom("mojom") {
"ct_log_info.mojom",
"digitally_signed.mojom",
"fetch_api.mojom",
"host_resolver.mojom",
"http_request_headers.mojom",
"network_change_manager.mojom",
"network_context.mojom",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module network.mojom;
import "net/interfaces/address_list.mojom";
// Control handle used to control outstanding NetworkContext::ResolveHost
// requests. Handle is optional for all requests, and may be closed at any time
// without affecting the request.
//
// TODO(crbug.com/821021): Add support to change priority.
interface ResolveHostHandle {
// Requests cancellation of the resolution request. Doing so may have no
// effect if a result was already sent. If successful, cancellation results in
// ResolveHostClient::OnComplete being invoked with |result|, which should be
// a non-OK network error code.
Cancel(int32 result);
};
// Response interface used to receive results of NetworkContext::ResolveHost
// requests.
//
// TODO(crbug.com/821021): Add additional methods to receive non-address
// results (eg TXT DNS responses).
interface ResolveHostClient {
// Called on completion of a resolve host request. Results are a network error
// code, and on success (network error code OK), an AddressList.
OnComplete(int32 result, net.interfaces.AddressList? resolved_addresses);
};
// TODO(crbug.com/821021): Create a separate HostResolver interface, so host
// resolution can be done without direct access to NetworkContext.
......@@ -13,7 +13,9 @@ import "net/interfaces/address_list.mojom";
import "net/interfaces/ip_endpoint.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/ct_log_info.mojom";
import "services/network/public/mojom/host_resolver.mojom";
import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/proxy_config.mojom";
import "services/network/public/mojom/proxy_config_with_annotation.mojom";
import "services/network/public/mojom/proxy_lookup_client.mojom";
......@@ -536,6 +538,29 @@ interface NetworkContext {
// used on URLLoaders.
ResetURLLoaderFactories();
// Resolves the given hostname (or IP address literal). All results are sent
// via the passed |response_client|. Results are a network error code, and on
// success (network error code OK), an AddressList.
//
// Results in ERR_NAME_NOT_RESOLVED if hostname is invalid, or if it is an
// incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6 literal).
//
// If passed an optional |control_handle|, the outstanding request can be
// controlled, eg cancelled, via the handle.
//
// All outstanding requests are cancelled if the NetworkContext is destroyed.
// Such requests will receive ERR_FAILED via |response_client|.
//
// TODO(crbug.com/821021): Implement more complex functionality to meet full
// capabilities of Resolve() and DnsClient/MDnsClient functionality.
//
// TODO(crbug.com/821021): Create (or move) a version of this API in some sort
// of separate (and possibly restrictable) HostResolver mojo interface that
// can be shared with processes without access to NetworkContext.
ResolveHost(HostPortPair host,
ResolveHostHandle&? control_handle,
ResolveHostClient response_client);
[Sync]
// Adds explicitly-specified data as if it was processed from an
// HSTS header.
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/resolve_host_request.h"
#include <utility>
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/optional.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/log/net_log_with_source.h"
namespace network {
ResolveHostRequest::ResolveHostRequest(net::HostResolver* resolver,
const net::HostPortPair& host,
net::NetLog* net_log) {
DCHECK(resolver);
DCHECK(net_log);
internal_request_ = resolver->CreateRequest(
host, net::NetLogWithSource::Make(net_log, net::NetLogSourceType::NONE));
}
ResolveHostRequest::~ResolveHostRequest() {
if (control_handle_binding_.is_bound())
control_handle_binding_.Close();
if (response_client_.is_bound()) {
response_client_->OnComplete(net::ERR_FAILED, base::nullopt);
response_client_ = nullptr;
}
}
int ResolveHostRequest::Start(
mojom::ResolveHostHandleRequest control_handle_request,
mojom::ResolveHostClientPtr response_client,
net::CompletionOnceCallback callback) {
DCHECK(internal_request_);
DCHECK(!control_handle_binding_.is_bound());
DCHECK(!response_client_.is_bound());
// Unretained |this| reference is safe because if |internal_request_| goes out
// of scope, it will cancel the request and ResolveHost() will not call the
// callback.
int rv = internal_request_->Start(
base::BindOnce(&ResolveHostRequest::OnComplete, base::Unretained(this)));
if (rv != net::ERR_IO_PENDING) {
response_client->OnComplete(rv, GetAddressResults());
return rv;
}
if (control_handle_request)
control_handle_binding_.Bind(std::move(control_handle_request));
response_client_ = std::move(response_client);
// Unretained |this| reference is safe because connection error cannot occur
// if |response_client_| goes out of scope.
response_client_.set_connection_error_handler(base::BindOnce(
&ResolveHostRequest::Cancel, base::Unretained(this), net::ERR_FAILED));
callback_ = std::move(callback);
return net::ERR_IO_PENDING;
}
void ResolveHostRequest::Cancel(int error) {
DCHECK_NE(net::OK, error);
if (cancelled_)
return;
internal_request_ = nullptr;
cancelled_ = true;
OnComplete(error);
}
void ResolveHostRequest::OnComplete(int error) {
DCHECK(response_client_.is_bound());
DCHECK(callback_);
control_handle_binding_.Close();
response_client_->OnComplete(error, GetAddressResults());
response_client_ = nullptr;
// Invoke completion callback last as it may delete |this|.
std::move(callback_).Run(error);
}
const base::Optional<net::AddressList>& ResolveHostRequest::GetAddressResults()
const {
if (cancelled_) {
static base::NoDestructor<base::Optional<net::AddressList>>
cancelled_result(base::nullopt);
return *cancelled_result;
}
DCHECK(internal_request_);
return internal_request_->GetAddressResults();
}
} // namespace network
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_NETWORK_RESOLVE_HOST_REQUEST_H_
#define SERVICES_NETWORK_RESOLVE_HOST_REQUEST_H_
#include <memory>
#include "base/macros.h"
#include "base/optional.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/completion_once_callback.h"
#include "net/dns/host_resolver.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
namespace net {
class HostPortPair;
class NetLog;
} // namespace net
namespace network {
// Manager of a single Mojo request to NetworkContext::ResolveHost(). Binds
// itself as the implementation of the control handle, and manages request
// lifetime and cancellation.
class ResolveHostRequest : public mojom::ResolveHostHandle {
public:
ResolveHostRequest(net::HostResolver* resolver,
const net::HostPortPair& host,
net::NetLog* net_log);
~ResolveHostRequest() override;
int Start(mojom::ResolveHostHandleRequest control_handle_request,
mojom::ResolveHostClientPtr response_client,
net::CompletionOnceCallback callback);
// ResolveHostHandle overrides.
void Cancel(int error) override;
private:
void OnComplete(int error);
const base::Optional<net::AddressList>& GetAddressResults() const;
std::unique_ptr<net::HostResolver::ResolveHostRequest> internal_request_;
mojo::Binding<mojom::ResolveHostHandle> control_handle_binding_{this};
mojom::ResolveHostClientPtr response_client_;
net::CompletionOnceCallback callback_;
bool cancelled_ = false;
DISALLOW_COPY_AND_ASSIGN(ResolveHostRequest);
};
} // namespace network
#endif // SERVICES_NETWORK_RESOLVE_HOST_REQUEST_H_
......@@ -104,6 +104,9 @@ class TestNetworkContext : public mojom::NetworkContext {
const GURL& url,
::network::mojom::ProxyLookupClientPtr proxy_lookup_client) override {}
void CreateNetLogExporter(mojom::NetLogExporterRequest exporter) override {}
void ResolveHost(const net::HostPortPair& host,
mojom::ResolveHostHandleRequest control_handle,
mojom::ResolveHostClientPtr response_client) override {}
void AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment