Skip to content

Commit

Permalink
Add support for DNSLink resolution
Browse files Browse the repository at this point in the history
13609: Added an Open in IPFS option for domains that have a TXT record that is prefixed with dnslink=
13611: Add a setting to automatically redirect for DNSLink
  • Loading branch information
spylogsster committed Mar 9, 2021
1 parent 0492014 commit 63dd112
Show file tree
Hide file tree
Showing 27 changed files with 1,211 additions and 10 deletions.
9 changes: 9 additions & 0 deletions app/brave_generated_resources.grd
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U
<message name="IDS_LOCATION_BAR_OPEN_IN_TOR" desc="Button in location bar to open onion available site in tor window.">
Open in Tor
</message>
<message name="IDS_LOCATION_BAR_OPEN_IN_IPFS" desc="Button in location bar to open ipfs available site.">
Open in IPFS
</message>
<message name="IDS_LOCATION_BAR_ONION_AVAILABLE" desc="Button in location bar to indicate onion available site to open a new tab in tor window.">
Onion Available
</message>
Expand Down Expand Up @@ -742,6 +745,12 @@ By installing this extension, you are agreeing to the Google Widevine Terms of U
<message name="IDS_SETTINGS_IPFS_AUTO_REDIRECT_GATEWAY_DESC" desc="The description for redirecting IPFS resources to the configured gateway">
Automatically uses the configured gateway for IPFS resolutions when an IPFS gateway resource is encountered.
</message>
<message name="IDS_SETTINGS_IPFS_AUTO_REDIRECT_DNSLINK_RESOURCES_LABEL" desc="The text label for redirecting IPFS resources for DNSLink">
Automatically redirect to IPFS pages via DNSLink when possible
</message>
<message name="IDS_SETTINGS_IPFS_AUTO_REDIRECT_DNSLINK_RESOURCES_DESC" desc="The description for redirecting IPFS resources for DNSLink">
Automatically uses DNSLink to navigate to an IPFS version of a website when possible
</message>
<message name="IDS_SETTINGS_HANGOUTS_ENABLED_DESC" desc="The description for Hangouts switch in settings">
Uses Hangouts component to enable screen sharing and other features in the browser.
</message>
Expand Down
1 change: 1 addition & 0 deletions app/vector_icons/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ aggregate_vector_icons("brave_vector_icons") {
"brave_ads_close_button.icon",
"brave_ads_info.icon",
"download_unlock.icon",
"open_in_ipfs.icon",
"open_in_tor.icon",
"speedreader.icon",
"speedreader_on_active.icon",
Expand Down
38 changes: 38 additions & 0 deletions app/vector_icons/open_in_ipfs.icon
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

CANVAS_DIMENSIONS, 12,
MOVE_TO, 11.5f, 10,
R_CUBIC_TO, -0.28f, 0, -0.5f, -0.22f, -0.5f, -0.5f,
V_LINE_TO, 1,
H_LINE_TO, 2.5f,
CUBIC_TO, 2.22f, 1, 2, 0.78f, 2, 0.5f,
R_CUBIC_TO, 0, -0.28f, 0.22f, -0.5f, 0.5f, -0.5f,
H_LINE_TO, 11,
R_CUBIC_TO, 0.55f, 0, 1, 0.45f, 1, 1,
R_V_LINE_TO, 8.5f,
R_CUBIC_TO, 0, 0.28f, -0.22f, 0.5f, -0.5f, 0.5f,
CLOSE,
MOVE_TO, 10, 3,
R_V_LINE_TO, 8,
R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -1, 1,
H_LINE_TO, 1,
R_CUBIC_TO, -0.55f, 0, -1, -0.45f, -1, -1,
V_LINE_TO, 3,
R_CUBIC_TO, 0, -0.55f, 0.45f, -1, 1, -1,
R_H_LINE_TO, 8,
R_CUBIC_TO, 0.55f, 0, 1, 0.45f, 1, 1,
CLOSE,
R_MOVE_TO, -9, 8,
R_H_LINE_TO, 8,
R_LINE_TO, 0, -6,
H_LINE_TO, 1,
R_V_LINE_TO, 6,
CLOSE,
R_MOVE_TO, 0, -7,
R_H_LINE_TO, 8,
V_LINE_TO, 3,
H_LINE_TO, 1,
R_V_LINE_TO, 1,
CLOSE
2 changes: 2 additions & 0 deletions browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ source_set("browser_process") {
sources += [
"ipfs/content_browser_client_helper.cc",
"ipfs/content_browser_client_helper.h",
"ipfs/ipfs_host_resolver.cc",
"ipfs/ipfs_host_resolver.h",
"ipfs/ipfs_service_factory.cc",
"ipfs/ipfs_service_factory.h",
"ipfs/ipfs_tab_helper.cc",
Expand Down
2 changes: 2 additions & 0 deletions browser/extensions/api/settings_private/brave_prefs_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ const PrefsUtil::TypedPrefMap& BravePrefsUtil::GetAllowlistedKeys() {
settings_api::PrefType::PREF_TYPE_STRING;
(*s_brave_allowlist)[kIPFSAutoRedirectGateway] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_brave_allowlist)[kIPFSAutoRedirectDNSLink] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
#endif
// Media Router Pref
(*s_brave_allowlist)[kBraveEnabledMediaRouter] =
Expand Down
106 changes: 106 additions & 0 deletions browser/ipfs/ipfs_host_resolver.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <utility>
#include <vector>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "brave/browser/ipfs/ipfs_host_resolver.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/host_port_pair.h"
#include "net/dns/public/dns_protocol.h"

namespace {

// DNSLink values are of the form: dnslink=<value>
// https://dnslink.io/#dnslink-format
const char kDnsLinkHeader[] = "dnslink";

// Expects dns TXT record in format: name=value
std::string GetDNSRecordValue(const std::vector<std::string>& text_results,
const std::string& name) {
for (const auto& txt : text_results) {
std::vector<std::string> tokens = base::SplitString(
txt, "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
if (!tokens.size())
continue;
if (tokens.front() != name)
continue;
return tokens.back();
}
return std::string();
}

} // namespace

namespace ipfs {

IPFSHostResolver::IPFSHostResolver(
network::mojom::NetworkContext* network_context,
const std::string& prefix)
: prefix_(prefix), network_context_(network_context) {
DCHECK(network_context);
}
IPFSHostResolver::~IPFSHostResolver() {}

void IPFSHostResolver::Resolve(const net::HostPortPair& host,
const net::NetworkIsolationKey& isolation_key,
net::DnsQueryType dns_query_type,
HostTextResultsCallback callback) {
if (!callback)
return;

if (host.host() == resolving_host_) {
if (callback && has_dnslink_) {
std::move(callback).Run(host.host());
}
return;
}

network::mojom::ResolveHostParametersPtr parameters =
network::mojom::ResolveHostParameters::New();
parameters->dns_query_type = dns_query_type;

receiver_.reset();
resolved_callback_ = std::move(callback);
has_dnslink_ = false;
resolving_host_ = host.host();
net::HostPortPair local_host_port(prefix_ + resolving_host_, host.port());

network_context_->ResolveHost(local_host_port, isolation_key,
std::move(parameters),
receiver_.BindNewPipeAndPassRemote());
}

void IPFSHostResolver::OnComplete(
int result,
const net::ResolveErrorInfo& error_info,
const base::Optional<net::AddressList>& list) {
if (result != net::OK) {
VLOG(1) << "DNS resolving error:" << net::ErrorToString(result)
<< " for host: " << prefix_ + resolving_host_;
}
if (complete_callback_for_testing_)
std::move(complete_callback_for_testing_).Run();
}

void IPFSHostResolver::OnTextResults(const std::vector<std::string>& results) {
VLOG(2) << results.size()
<< " TXT records resolved for host: " << prefix_ + resolving_host_;
std::string dnslink = GetDNSRecordValue(results, kDnsLinkHeader);
has_dnslink_ = !dnslink.empty();
// We intentionally ignore the value since only its presence is important
// to us. https://docs.ipfs.io/concepts/dnslink/#publish-using-a-subdomain
if (!has_dnslink_)
return;

if (resolved_callback_)
std::move(resolved_callback_).Run(resolving_host_);
}

} // namespace ipfs
65 changes: 65 additions & 0 deletions browser/ipfs/ipfs_host_resolver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_IPFS_IPFS_HOST_RESOLVER_H_
#define BRAVE_BROWSER_IPFS_IPFS_HOST_RESOLVER_H_

#include <string>
#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "net/base/host_port_pair.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/public/dns_query_type.h"
#include "services/network/public/cpp/resolve_host_client_base.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"

namespace ipfs {

// Resolves DNS TXT record for hosts. If prefix passed then
// automatically adds it to the host.
class IPFSHostResolver : public network::ResolveHostClientBase {
public:
explicit IPFSHostResolver(network::mojom::NetworkContext* network_context,
const std::string& prefix = std::string());
~IPFSHostResolver() override;

using HostTextResultsCallback =
base::OnceCallback<void(const std::string& host)>;

virtual void Resolve(const net::HostPortPair& host,
const net::NetworkIsolationKey& isolation_key,
net::DnsQueryType dns_query_type,
HostTextResultsCallback callback);

std::string host() const { return resolving_host_; }

void SetCompleteCallbackForTesting(base::OnceClosure complete_callback) {
complete_callback_for_testing_ = std::move(complete_callback);
}

private:
// network::mojom::ResolveHostClient implementation:
void OnComplete(
int result,
const net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) override;
void OnTextResults(const std::vector<std::string>& text_results) override;

std::string resolving_host_;
std::string prefix_;
bool has_dnslink_ = false;
network::mojom::NetworkContext* network_context_ = nullptr;
HostTextResultsCallback resolved_callback_;
base::OnceClosure complete_callback_for_testing_;

mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
};

} // namespace ipfs

#endif // BRAVE_BROWSER_IPFS_IPFS_HOST_RESOLVER_H_
Loading

0 comments on commit 63dd112

Please sign in to comment.