Skip to content

Commit

Permalink
web_utils
Browse files Browse the repository at this point in the history
  • Loading branch information
John-LittleBearLabs committed Feb 8, 2024
1 parent 6163de3 commit a9b18bf
Show file tree
Hide file tree
Showing 23 changed files with 167 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ index 23ee785c34a30..8550b43c61f2f 100644
RenderFrameHost::FromID(render_process_id, render_frame_id);
WebContents* web_contents = WebContents::FromRenderFrameHost(frame_host);
#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(ENABLE_EXTENSIONS) || \
// !BUILDFLAG(IS_ANDROID)
- // !BUILDFLAG(IS_ANDROID)
+ // !BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_IPFS)
+#if BUILDFLAG(ENABLE_IPFS)
+ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) {
+ network::mojom::URLLoaderFactory* default_factory = g_browser_process->system_network_context_manager()->GetURLLoaderFactory();
Expand Down
3 changes: 1 addition & 2 deletions component/cache_requestor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ void Self::OnHeaderRead(Task task, int code) {
}
void Self::OnBodyRead(Task task, int code) {
if (code <= 0) {
LOG(INFO) << "Failed to read body for entry " << task.key << " in "
<< name();
VLOG(1) << "Failed to read body for entry " << task.key << " in " << name();
Miss(task);
return;
}
Expand Down
13 changes: 13 additions & 0 deletions component/chromium_cbor_adapter.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
#include "chromium_cbor_adapter.h"

#include <base/logging.h>
#include <components/cbor/reader.h>

using Self = ipfs::ChromiumCborAdapter;

auto Self::Parse(ipfs::ByteView bytes) -> std::unique_ptr<DagCborValue> {
cbor::Reader::Config cfg;
cfg.parse_tags = true;
auto parsed = cbor::Reader::Read(as_octets(bytes), cfg);
if (parsed.has_value()) {
return std::make_unique<ChromiumCborAdapter>(std::move(parsed.value()));
}
LOG(ERROR) << "Failed to parse CBOR.";
return {};
}

bool Self::is_map() const {
return cbor_.is_map();
}
Expand Down Expand Up @@ -83,6 +95,7 @@ void Self::iterate_array(ArrayElementCallback cb) const {
}
}

Self::ChromiumCborAdapter() : cbor_{cbor::Value::SimpleValue::UNDEFINED} {}
Self::ChromiumCborAdapter(cbor::Value const& v) : cbor_{v.Clone()} {}
Self::ChromiumCborAdapter(cbor::Value&& v) : cbor_{std::move(v)} {}
Self::ChromiumCborAdapter(ChromiumCborAdapter const& rhs)
Expand Down
8 changes: 6 additions & 2 deletions component/chromium_cbor_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

#include <components/cbor/values.h>

#include <ipfs_client/context_api.h>
#include <ipfs_client/ctx/cbor_parser.h>
#include <ipfs_client/dag_cbor_value.h>

namespace ipfs {
class ChromiumCborAdapter final : public DagCborValue {
class ChromiumCborAdapter final : public DagCborValue, public ctx::CborParser {
cbor::Value cbor_;

std::unique_ptr<DagCborValue> at(std::string_view) const override;
Expand All @@ -23,10 +24,13 @@ class ChromiumCborAdapter final : public DagCborValue {
void iterate_array(ArrayElementCallback) const override;

public:
explicit ChromiumCborAdapter();
ChromiumCborAdapter(cbor::Value&&);
ChromiumCborAdapter(cbor::Value const&);
ChromiumCborAdapter(ChromiumCborAdapter const& rhs);
~ChromiumCborAdapter() noexcept override;

std::unique_ptr<DagCborValue> Parse(ByteView) override;
};
} // namespace ipfs

Expand Down
26 changes: 11 additions & 15 deletions component/chromium_ipfs_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#include "chromium_http.h"
#include "chromium_json_adapter.h"
#include "inter_request_state.h"
#include "json_parser_adapter.h"

#include <components/cbor/reader.h>
#include <services/network/public/cpp/simple_url_loader.h>
#include <services/network/public/mojom/url_response_head.mojom.h>

Expand All @@ -30,9 +30,10 @@ void Self::SetupHttp(network::mojom::URLLoaderFactory& lf) {
http_api_ = std::make_unique<ChromiumHttp>(lf);
}

std::string Self::MimeType(std::string extension,
namespace {
std::string DeduceMimeType(std::string extension,
std::string_view content,
std::string const& url) const {
std::string const& url) {
std::string result;
auto fp_ext = base::FilePath::FromUTF8Unsafe(extension).value();
if (extension.empty()) {
Expand All @@ -49,27 +50,22 @@ std::string Self::MimeType(std::string extension,
}
return result;
}
std::string Self::UnescapeUrlComponent(std::string_view comp) const {
std::string Unescape(std::string_view comp) {
using Rule = base::UnescapeRule;
auto rules = Rule::PATH_SEPARATORS |
Rule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS | Rule::SPACES;
auto result = base::UnescapeURLComponent({comp.data(), comp.size()}, rules);
return result;
}
auto Self::ParseCbor(ipfs::ContextApi::ByteView bytes) const
-> std::unique_ptr<DagCborValue> {
cbor::Reader::Config cfg;
cfg.parse_tags = true;
auto parsed = cbor::Reader::Read(as_octets(bytes), cfg);
if (parsed.has_value()) {
return std::make_unique<ChromiumCborAdapter>(std::move(parsed.value()));
}
LOG(ERROR) << "Failed to parse CBOR.";
return {};
}
} // namespace

Self::ChromiumIpfsContext(InterRequestState& state, PrefService* prefs) {
with(std::make_unique<ChromiumIpfsGatewayConfig>(prefs));
with(std::make_unique<ChromiumDnsTxtLookup>(state));
with(&DeduceMimeType);
with(&Unescape);
with(std::make_unique<ChromiumCborAdapter>());
with(std::make_unique<JsonParserAdapter>());
using K = crypto::SigningKeyType;
with(K::RSA,
std::make_unique<crypto::OpensslSignatureVerifier>(EVP_PKEY_RSA));
Expand Down
6 changes: 0 additions & 6 deletions component/chromium_ipfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ class IpfsRequest;
class NetworkRequestor;

class ChromiumIpfsContext final : public ContextApi {
std::string MimeType(std::string extension,
std::string_view content,
std::string const& url) const override;
std::string UnescapeUrlComponent(std::string_view) const override;

std::unique_ptr<DagCborValue> ParseCbor(ByteView) const override;

public:
ChromiumIpfsContext(InterRequestState&, PrefService* prefs);
Expand Down
2 changes: 1 addition & 1 deletion component/ipfs_url_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void ipfs::IpfsUrlLoader::BlocksComplete(std::string mime_type) {

void ipfs::IpfsUrlLoader::DoesNotExist(std::string_view cid,
std::string_view path) {
LOG(WARNING) << "Immutable data 404 for " << cid << '/' << path;
LOG(INFO) << "Immutable data 404 for " << cid << '/' << path;
complete_ = true;
client_->OnComplete(
network::URLLoaderCompletionStatus{net::ERR_FILE_NOT_FOUND});
Expand Down
17 changes: 11 additions & 6 deletions library/include/ipfs_client/context_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class DagCborValue;
class ContextApi : public std::enable_shared_from_this<ContextApi> {
public:
using SigningKeyType = ::ipfs::crypto::SigningKeyType;
using MimeTypeDeduction = std::function<
std::string(std::string, std::string_view, std::string const&)>;
using UrlUnescaping = std::function<std::string(std::string_view)>;

ContextApi();
virtual ~ContextApi() noexcept {}
Expand All @@ -55,26 +58,26 @@ class ContextApi : public std::enable_shared_from_this<ContextApi> {
ContextApi& with(std::unique_ptr<ctx::JsonParser>);
ContextApi& with(std::unique_ptr<ctx::CborParser>);
ContextApi& with(SigningKeyType, std::unique_ptr<crypto::SignatureVerifier>);
ContextApi& with(MimeTypeDeduction);
ContextApi& with(UrlUnescaping);

/*!
* \brief Determine a mime type for a given file.
* \param extension - "File extension" not including ., e.g. "html"
* \param content - The content of the resource or a large prefix thereof
* \param url - A URL it was fetched from (of any sort, ipfs:// is fine)
*/
virtual std::string MimeType(std::string extension,
std::string_view content,
std::string const& url) const = 0;
std::string MimeType(std::string extension,
std::string_view content,
std::string const& url);

/*!
* \brief Remove URL escaping, e.g. %20
* \param url_comp - a single component of the URL, e.g. a element of the path
* not including /
* \return The unescaped string
*/
virtual std::string UnescapeUrlComponent(std::string_view url_comp) const = 0;

virtual std::unique_ptr<DagCborValue> ParseCbor(ByteView) const = 0;
std::string UnescapeUrlComponent(std::string_view url_comp);

using ByteView = ::ipfs::ByteView;
bool VerifyKeySignature(SigningKeyType,
Expand All @@ -93,6 +96,8 @@ class ContextApi : public std::enable_shared_from_this<ContextApi> {
std::unique_ptr<ctx::GatewayConfig> gateway_config_;
std::unique_ptr<ctx::JsonParser> json_parser_;
std::unique_ptr<ctx::CborParser> cbor_parser_;
MimeTypeDeduction deduce_mime_type_;
UrlUnescaping unescape_;
};

} // namespace ipfs
Expand Down
2 changes: 1 addition & 1 deletion library/include/ipfs_client/ipld/resolution_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ResolutionState {
SlashDelimited MyPath() const;
SlashDelimited PathToResolve() const;
bool IsFinalComponent() const;
std::string NextComponent(ContextApi const*) const;
std::string NextComponent(ContextApi*) const;
NodePtr GetBlock(std::string const& block_key) const;

ResolutionState WithPath(std::string_view) const;
Expand Down
45 changes: 0 additions & 45 deletions library/include/ipfs_client/test_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,51 +45,6 @@ namespace ipfs {
// LCOV_EXCL_START

class TestContext final : public ContextApi {
std::string MimeType(std::string extension,
std::string_view,
std::string const&) const override {
// TODO implement real mime type detection
return "text/" + extension;
}
std::string UnescapeUrlComponent(std::string_view url_comp) const override {
std::string rv{url_comp};
auto xval = [](char c) {
if (c <= '9') {
return c - '0';
}
if (c <= 'Z') {
return c - 'A';
}
return c - 'a';
};
for (auto i = 0UL; i + 1UL < rv.size(); ++i) {
if (rv[i] != '%') {
continue;
}
auto a = rv[i + 1UL];
if (rv[i + 1UL] == '%') {
rv.erase(i, 1UL);
continue;
}
if (i + 2UL >= rv.size()) {
break;
}
if (!std::isxdigit(a)) {
continue;
}
auto b = rv[i + 2UL];
if (std::isxdigit(b)) {
rv[i] = xval(a) * 16 + xval(b);
rv.erase(i + 1UL, 2);
}
}
return rv;
}
std::unique_ptr<DagCborValue> ParseCbor(ByteView bytes) const override {
auto data = nlohmann::json::from_cbor(
bytes, false, true, nlohmann::detail::cbor_tag_handler_t::store);
return std::make_unique<ipfs::JsonCborAdapter>(data);
}
boost::asio::io_context& io_;

public:
Expand Down
8 changes: 4 additions & 4 deletions library/src/ipfs_client/car.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ using ByteView = ipfs::ByteView;
using VarInt = libp2p::multi::UVarint;

namespace {
short ReadHeader(ByteView&, ipfs::ContextApi const&);
short ReadHeader(ByteView&, ipfs::ContextApi&);
std::pair<std::uint64_t, std::uint64_t> GetV1PayloadPos(ByteView);
} // namespace

Self::Car(ByteView bytes, ContextApi const& api) {
Self::Car(ByteView bytes, ContextApi& api) {
auto after_header = bytes;
auto version = ReadHeader(after_header, api);
switch (version) {
Expand Down Expand Up @@ -65,15 +65,15 @@ auto Self::NextBlock() -> std::optional<Block> {

namespace {
// https://ipld.io/specs/transport/car/carv2/
short ReadHeader(ByteView& bytes, ipfs::ContextApi const& api) {
short ReadHeader(ByteView& bytes, ipfs::ContextApi& api) {
auto header_len = VarInt::create(bytes);
if (!header_len ||
header_len->toUInt64() + header_len->size() > bytes.size()) {
return 0;
}
bytes = bytes.subspan(header_len->size());
auto header_bytes = bytes.subspan(0UL, header_len->toUInt64());
auto header = api.ParseCbor(header_bytes);
auto header = api.cbor().Parse(header_bytes);
if (!header) {
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion library/src/ipfs_client/car.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace ipfs {
class ContextApi;
class Car {
public:
Car(ByteView, ContextApi const&);
Car(ByteView, ContextApi&);
struct Block {
Cid cid;
ByteView bytes;
Expand Down
27 changes: 27 additions & 0 deletions library/src/ipfs_client/context_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ipfs_client/ctx/null_dns_txt_lookup.h"
#include "ipfs_client/ctx/null_http_provider.h"
#include "ipfs_client/ctx/transitory_gateway_config.h"
#include "ipfs_client/web_util.h"

#include "log_macros.h"

Expand Down Expand Up @@ -47,6 +48,24 @@ bool Self::VerifyKeySignature(SigningKeyType typ,
}
return it->second->VerifySignature(signature, data, key_bytes);
}
std::string Self::MimeType(std::string extension,
std::string_view content,
std::string const& url) {
if (!deduce_mime_type_) {
LOG(WARNING) << "No mime-type deduction algo provided. Will do something "
"trivial/inaccurate.";
deduce_mime_type_ = util::TrivialMimeGuess;
}
return deduce_mime_type_(extension, content, url);
}
std::string Self::UnescapeUrlComponent(std::string_view url_comp) {
if (!unescape_) {
LOG(WARNING)
<< "No URL (un)escaping algo provided. Will do something simple/wrong.";
unescape_ = util::RoughlyUnescapeUrlComponent;
}
return unescape_(url_comp);
}

auto Self::http() -> ctx::HttpApi& {
if (!http_api_) {
Expand Down Expand Up @@ -114,6 +133,14 @@ Self& Self::with(SigningKeyType t,
}
return *this;
}
Self& Self::with(ipfs::ContextApi::MimeTypeDeduction deduce_mime_type) {
deduce_mime_type_ = deduce_mime_type;
return *this;
}
Self& Self::with(ipfs::ContextApi::UrlUnescaping unescape) {
unescape_ = unescape;
return *this;
}
Self& Self::with(std::unique_ptr<ctx::GatewayConfig> p) {
gateway_config_ = std::move(p);
return *this;
Expand Down
Loading

0 comments on commit a9b18bf

Please sign in to comment.