diff --git a/.github/workflows/library.yml b/.github/workflows/library.yml index e4a4a452..0605c056 100644 --- a/.github/workflows/library.yml +++ b/.github/workflows/library.yml @@ -29,7 +29,7 @@ jobs: config: - { name: "macOS", - os: macos-12, + os: macos-latest, build_type: "Release", cc: "clang", cxx: "clang++", diff --git a/chromium_edits/122.0.6194.0/chrome/browser/BUILD.gn.patch b/chromium_edits/122.0.6194.0/chrome/browser/BUILD.gn.patch new file mode 100644 index 00000000..3f644ee6 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/BUILD.gn.patch @@ -0,0 +1,27 @@ +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +index ea574b1863e18..7239008b4e215 100644 +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -39,6 +39,7 @@ import("//rlz/buildflags/buildflags.gni") + import("//sandbox/features.gni") + import("//testing/libfuzzer/fuzzer_test.gni") + import("//third_party/blink/public/public_features.gni") ++import("//third_party/ipfs_client/args.gni") + import("//third_party/protobuf/proto_library.gni") + import("//third_party/webrtc/webrtc.gni") + import("//third_party/widevine/cdm/widevine.gni") +@@ -2615,6 +2616,14 @@ static_library("browser") { + ] + } + ++ if (enable_ipfs) { ++ sources += [ ++ "ipfs_extra_parts.cc", ++ "ipfs_extra_parts.h", ++ ] ++ deps += [ "//components/ipfs" ] ++ } ++ + if (is_chromeos_ash) { + deps += [ "//chrome/browser/screen_ai:screen_ai_dlc_installer" ] + } diff --git a/chromium_edits/122.0.6194.0/chrome/browser/about_flags.cc.patch b/chromium_edits/122.0.6194.0/chrome/browser/about_flags.cc.patch new file mode 100644 index 00000000..6e4ac390 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/about_flags.cc.patch @@ -0,0 +1,38 @@ +diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc +index b076446400486..2b2f2724d3b75 100644 +--- a/chrome/browser/about_flags.cc ++++ b/chrome/browser/about_flags.cc +@@ -214,6 +214,7 @@ + #include "third_party/blink/public/common/features_generated.h" + #include "third_party/blink/public/common/forcedark/forcedark_switches.h" + #include "third_party/blink/public/common/switches.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + #include "ui/accessibility/accessibility_features.h" + #include "ui/accessibility/accessibility_switches.h" + #include "ui/base/ozone_buildflags.h" +@@ -310,6 +311,10 @@ + #include "extensions/common/switches.h" + #endif // BUILDFLAG(ENABLE_EXTENSIONS) + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#endif ++ + #if BUILDFLAG(ENABLE_PDF) + #include "pdf/pdf_features.h" + #endif +@@ -9459,6 +9464,14 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kOmitCorsClientCertDescription, kOsAll, + FEATURE_VALUE_TYPE(network::features::kOmitCorsClientCert)}, + ++#if BUILDFLAG(ENABLE_IPFS) ++ {"enable-ipfs", ++ flag_descriptions::kEnableIpfsName, ++ flag_descriptions::kEnableIpfsDescription, ++ kOsMac | kOsWin | kOsLinux,//TODO: These are the only variants currently getting built, but that is not likely to remain the case ++ FEATURE_VALUE_TYPE(ipfs::kEnableIpfs)}, ++#endif ++ + {"use-idna2008-non-transitional", + flag_descriptions::kUseIDNA2008NonTransitionalName, + flag_descriptions::kUseIDNA2008NonTransitionalDescription, kOsAll, diff --git a/chromium_edits/122.0.6194.0/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc.patch b/chromium_edits/122.0.6194.0/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc.patch new file mode 100644 index 00000000..4d172311 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc.patch @@ -0,0 +1,50 @@ +diff --git a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc +index 4c88614c68c25..f8bb12a3b0c2e 100644 +--- a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc ++++ b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc +@@ -10,6 +10,8 @@ + #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" + #include "chrome/browser/external_protocol/external_protocol_handler.h" + #include "chrome/browser/profiles/profile.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" ++ + #if BUILDFLAG(IS_ANDROID) + #include "chrome/browser/profiles/profile_android.h" + #endif +@@ -18,6 +20,9 @@ + #include "chrome/browser/ui/android/omnibox/jni_headers/ChromeAutocompleteSchemeClassifier_jni.h" + #endif + #include "components/custom_handlers/protocol_handler_registry.h" ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#endif + #include "content/public/common/url_constants.h" + #include "url/url_util.h" + +@@ -55,12 +60,20 @@ ChromeAutocompleteSchemeClassifier::GetInputTypeForScheme( + if (scheme.empty()) { + return metrics::OmniboxInputType::EMPTY; + } +- if (base::IsStringASCII(scheme) && +- (ProfileIOData::IsHandledProtocol(scheme) || +- base::EqualsCaseInsensitiveASCII(scheme, content::kViewSourceScheme) || +- base::EqualsCaseInsensitiveASCII(scheme, url::kJavaScriptScheme) || +- base::EqualsCaseInsensitiveASCII(scheme, url::kDataScheme))) { +- return metrics::OmniboxInputType::URL; ++ if (base::IsStringASCII(scheme)) { ++ if (ProfileIOData::IsHandledProtocol(scheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, content::kViewSourceScheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, url::kJavaScriptScheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, url::kDataScheme)) { ++ return metrics::OmniboxInputType::URL; ++ } ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs) && ++ (base::EqualsCaseInsensitiveASCII(scheme, "ipfs") || base::EqualsCaseInsensitiveASCII(scheme, "ipns")) ++ ) { ++ return metrics::OmniboxInputType::URL; ++ } ++#endif + } + + // Also check for schemes registered via registerProtocolHandler(), which diff --git a/chromium_edits/122.0.6194.0/chrome/browser/chrome_content_browser_client.cc.patch b/chromium_edits/122.0.6194.0/chrome/browser/chrome_content_browser_client.cc.patch new file mode 100644 index 00000000..2f68a7f3 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/chrome_content_browser_client.cc.patch @@ -0,0 +1,77 @@ +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +index 667370e623970..c09550c753e8e 100644 +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -377,6 +377,7 @@ + #include "third_party/blink/public/common/switches.h" + #include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h" + #include "third_party/blink/public/public_buildflags.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + #include "third_party/widevine/cdm/buildflags.h" + #include "ui/base/clipboard/clipboard_format_type.h" + #include "ui/base/l10n/l10n_util.h" +@@ -499,6 +500,13 @@ + #include "chrome/browser/fuchsia/chrome_browser_main_parts_fuchsia.h" + #endif + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "chrome/browser/ipfs_extra_parts.h" ++#include "components/ipfs/interceptor.h" ++#include "components/ipfs/ipfs_features.h" ++#include "components/ipfs/url_loader_factory.h" ++#endif ++ + #if BUILDFLAG(IS_CHROMEOS) + #include "base/debug/leak_annotations.h" + #include "chrome/browser/apps/app_service/app_install/app_install_navigation_throttle.h" +@@ -1711,6 +1719,11 @@ ChromeContentBrowserClient::CreateBrowserMainParts(bool is_integration_test) { + main_parts->AddParts( + std::make_unique()); + ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ main_parts->AddParts(std::make_unique()); ++ } ++#endif + return main_parts; + } + +@@ -6075,12 +6088,25 @@ void ChromeContentBrowserClient:: + const absl::optional& request_initiator_origin, + NonNetworkURLLoaderFactoryMap* factories) { + #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(ENABLE_EXTENSIONS) || \ +- !BUILDFLAG(IS_ANDROID) ++ !BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_IPFS) + content::RenderFrameHost* frame_host = + 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) ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ network::mojom::URLLoaderFactory* default_factory = g_browser_process->system_network_context_manager()->GetURLLoaderFactory(); ++ auto* context = web_contents->GetBrowserContext(); ++ ipfs::IpfsURLLoaderFactory::Create( ++ factories, ++ context, ++ default_factory, ++ GetSystemNetworkContext(), ++ Profile::FromBrowserContext(context)->GetPrefs() ++ ); ++ } ++#endif // BUILDFLAG(ENABLE_IPFS) + + #if BUILDFLAG(IS_CHROMEOS_ASH) + if (web_contents) { +@@ -6222,6 +6248,11 @@ ChromeContentBrowserClient::WillCreateURLLoaderRequestInterceptors( + scoped_refptr navigation_response_task_runner) { + std::vector> + interceptors; ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ interceptors.push_back(std::make_unique(g_browser_process->system_network_context_manager()->GetURLLoaderFactory(), GetSystemNetworkContext())); ++ } ++#endif + #if BUILDFLAG(ENABLE_OFFLINE_PAGES) + interceptors.push_back( + std::make_unique( diff --git a/chromium_edits/122.0.6194.0/chrome/browser/flag-metadata.json.patch b/chromium_edits/122.0.6194.0/chrome/browser/flag-metadata.json.patch new file mode 100644 index 00000000..75727bd8 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/flag-metadata.json.patch @@ -0,0 +1,16 @@ +diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json +index 7a0c7c06f4e8e..8af9a104e1fe8 100644 +--- a/chrome/browser/flag-metadata.json ++++ b/chrome/browser/flag-metadata.json +@@ -2931,6 +2931,11 @@ + "owners": [ "hanxi@chromium.org", "wychen@chromium.org" ], + "expiry_milestone": 130 + }, ++ { ++ "name": "enable-ipfs", ++ "owners": [ "//components/ipfs/OWNERS" ], ++ "expiry_milestone": 150 ++ }, + { + "name": "enable-isolated-sandboxed-iframes", + "owners": [ "wjmaclean@chromium.org", "alexmos@chromium.org", "creis@chromium.org" ], diff --git a/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.cc.patch b/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.cc.patch new file mode 100644 index 00000000..a687852a --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.cc.patch @@ -0,0 +1,16 @@ +diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc +index b4f75320e4669..fc2ef00f6eb5c 100644 +--- a/chrome/browser/flag_descriptions.cc ++++ b/chrome/browser/flag_descriptions.cc +@@ -289,6 +289,11 @@ const char kEnableBenchmarkingDescription[] = + "after 3 restarts. On the third restart, the flag will appear to be off " + "but the effect is still active."; + ++#if BUILDFLAG(ENABLE_IPFS) ++extern const char kEnableIpfsName[] = "Enable IPFS"; ++extern const char kEnableIpfsDescription[] = "Enable ipfs:// and ipns:// URLs"; ++#endif ++ + const char kPreloadingOnPerformancePageName[] = + "Preloading Settings on Performance Page"; + const char kPreloadingOnPerformancePageDescription[] = diff --git a/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.h.patch b/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.h.patch new file mode 100644 index 00000000..40c0f537 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/flag_descriptions.h.patch @@ -0,0 +1,24 @@ +diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h +index 65b8bcb40770c..d5ae8dca53910 100644 +--- a/chrome/browser/flag_descriptions.h ++++ b/chrome/browser/flag_descriptions.h +@@ -23,6 +23,7 @@ + #include "pdf/buildflags.h" + #include "printing/buildflags/buildflags.h" + #include "third_party/blink/public/common/buildflags.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + + // This file declares strings used in chrome://flags. These messages are not + // translated, because instead of end-users they target Chromium developers and +@@ -179,6 +180,11 @@ extern const char kDownloadWarningImprovementsDescription[]; + extern const char kEnableBenchmarkingName[]; + extern const char kEnableBenchmarkingDescription[]; + ++#if BUILDFLAG(ENABLE_IPFS) ++extern const char kEnableIpfsName[]; ++extern const char kEnableIpfsDescription[]; ++#endif ++ + #if BUILDFLAG(USE_FONTATIONS_BACKEND) + extern const char kFontationsFontBackendName[]; + extern const char kFontationsFontBackendDescription[]; diff --git a/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.cc b/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.cc new file mode 100644 index 00000000..90d2596f --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.cc @@ -0,0 +1,10 @@ +#include "ipfs_extra_parts.h" + +#include "profiles/profile.h" + +#include + +void IpfsExtraParts::PostProfileInit(Profile* profile, bool /* is_initial_profile */ ) { + DCHECK(profile); + ipfs::InterRequestState::CreateForBrowserContext(profile, profile->GetPrefs()); +} diff --git a/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.h b/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.h new file mode 100644 index 00000000..2059c437 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/ipfs_extra_parts.h @@ -0,0 +1,10 @@ +#ifndef IPFS_EXTRA_PART_H_ +#define IPFS_EXTRA_PART_H_ + +#include + +class IpfsExtraParts : public ChromeBrowserMainExtraParts { + void PostProfileInit(Profile* profile, bool is_initial_profile) override; +}; + +#endif // IPFS_EXTRA_PART_H_ diff --git a/chromium_edits/122.0.6194.0/chrome/browser/prefs/browser_prefs.cc.patch b/chromium_edits/122.0.6194.0/chrome/browser/prefs/browser_prefs.cc.patch new file mode 100644 index 00000000..c32f6471 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/browser/prefs/browser_prefs.cc.patch @@ -0,0 +1,36 @@ +diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc +index 86a09cfe49376..d8e166f76179e 100644 +--- a/chrome/browser/prefs/browser_prefs.cc ++++ b/chrome/browser/prefs/browser_prefs.cc +@@ -189,6 +189,7 @@ + #include "printing/buildflags/buildflags.h" + #include "rlz/buildflags/buildflags.h" + #include "third_party/abseil-cpp/absl/types/optional.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + + #if BUILDFLAG(ENABLE_BACKGROUND_MODE) + #include "chrome/browser/background/background_mode_manager.h" +@@ -233,6 +234,11 @@ + #include "chrome/browser/pdf/pdf_pref_names.h" + #endif // BUILDFLAG(ENABLE_PDF) + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#include "components/ipfs/preferences.h" ++#endif ++ + #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + #include "chrome/browser/screen_ai/pref_names.h" + #endif +@@ -1678,6 +1684,11 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, + IncognitoModePrefs::RegisterProfilePrefs(registry); + invalidation::PerUserTopicSubscriptionManager::RegisterProfilePrefs(registry); + invalidation::InvalidatorRegistrarWithMemory::RegisterProfilePrefs(registry); ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ ipfs::RegisterPreferences(registry); ++ } ++#endif + language::LanguagePrefs::RegisterProfilePrefs(registry); + login_detection::prefs::RegisterProfilePrefs(registry); + lookalikes::RegisterProfilePrefs(registry); diff --git a/chromium_edits/122.0.6194.0/chrome/common/chrome_content_client.cc.patch b/chromium_edits/122.0.6194.0/chrome/common/chrome_content_client.cc.patch new file mode 100644 index 00000000..5bd09f16 --- /dev/null +++ b/chromium_edits/122.0.6194.0/chrome/common/chrome_content_client.cc.patch @@ -0,0 +1,17 @@ +diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc +index 246ec9c5c911f..5d66d133a7907 100644 +--- a/chrome/common/chrome_content_client.cc ++++ b/chrome/common/chrome_content_client.cc +@@ -296,6 +296,12 @@ void ChromeContentClient::AddAdditionalSchemes(Schemes* schemes) { + #if BUILDFLAG(IS_ANDROID) + schemes->local_schemes.push_back(url::kContentScheme); + #endif ++ for ( const char* ip_s : {"ipfs", "ipns"} ) { ++ schemes->standard_schemes.push_back(ip_s); ++ schemes->cors_enabled_schemes.push_back(ip_s); ++ schemes->secure_schemes.push_back(ip_s); ++ schemes->csp_bypassing_schemes.push_back(ip_s); ++ } + } + + std::u16string ChromeContentClient::GetLocalizedString(int message_id) { diff --git a/chromium_edits/122.0.6194.0/components/cbor/reader.cc.patch b/chromium_edits/122.0.6194.0/components/cbor/reader.cc.patch new file mode 100644 index 00000000..aed86452 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/reader.cc.patch @@ -0,0 +1,44 @@ +diff --git a/components/cbor/reader.cc b/components/cbor/reader.cc +index 306ba52fa4944..6b13b3a679a65 100644 +--- a/components/cbor/reader.cc ++++ b/components/cbor/reader.cc +@@ -22,7 +22,7 @@ + namespace cbor { + + namespace constants { +-const char kUnsupportedMajorType[] = "Unsupported major type."; ++const char kUnsupportedMajorType[] = "Unsupported major type operation."; + } + + namespace { +@@ -156,7 +156,11 @@ absl::optional Reader::DecodeCompleteDataItem(const Config& config, + case Value::Type::FLOAT_VALUE: + // Floating point values also go here since they are also type 7. + return DecodeToSimpleValueOrFloat(*header, config); +- case Value::Type::TAG: // We explicitly don't support TAG. ++ case Value::Type::TAG: ++ if (config.parse_tags) { ++ return ReadTagContent(*header, config, max_nesting_level); ++ } ++ break; + case Value::Type::NONE: + case Value::Type::INVALID_UTF8: + break; +@@ -347,6 +351,17 @@ absl::optional Reader::ReadByteStringContent( + return Value(std::move(cbor_byte_string)); + } + ++absl::optional Reader::ReadTagContent( ++ const Reader::DataItemHeader& header, ++ const Config& config, ++ int max_nesting_level) { ++ auto tagged_content = DecodeCompleteDataItem(config, max_nesting_level); ++ if (tagged_content.has_value()) { ++ tagged_content.value().SetTag(header.value); ++ } ++ return tagged_content; ++} ++ + absl::optional Reader::ReadArrayContent( + const Reader::DataItemHeader& header, + const Config& config, diff --git a/chromium_edits/122.0.6194.0/components/cbor/reader.h.patch b/chromium_edits/122.0.6194.0/components/cbor/reader.h.patch new file mode 100644 index 00000000..fb821165 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/reader.h.patch @@ -0,0 +1,26 @@ +diff --git a/components/cbor/reader.h b/components/cbor/reader.h +index f0b43a5517528..a57e277a1bc66 100644 +--- a/components/cbor/reader.h ++++ b/components/cbor/reader.h +@@ -130,6 +130,11 @@ class CBOR_EXPORT Reader { + // during decoding will set raise the `UNSUPPORTED_FLOATING_POINT_VALUE` + // error. + bool allow_floating_point = false; ++ ++ // If the parser encounters a TAG element, should it be parsed out and ++ // the tag value saved (true), or should the entire node and its content ++ // be discarded (false) ++ bool parse_tags = false; + }; + + Reader(const Reader&) = delete; +@@ -204,6 +209,9 @@ class CBOR_EXPORT Reader { + absl::optional ReadMapContent(const DataItemHeader& header, + const Config& config, + int max_nesting_level); ++ absl::optional ReadTagContent(const DataItemHeader& header, ++ const Config& config, ++ int max_nesting_level); + absl::optional ReadByte(); + absl::optional> ReadBytes(uint64_t num_bytes); + bool IsKeyInOrder(const Value& new_key, diff --git a/chromium_edits/122.0.6194.0/components/cbor/reader_unittest.cc.patch b/chromium_edits/122.0.6194.0/components/cbor/reader_unittest.cc.patch new file mode 100644 index 00000000..3f657dc3 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/reader_unittest.cc.patch @@ -0,0 +1,47 @@ +diff --git a/components/cbor/reader_unittest.cc b/components/cbor/reader_unittest.cc +index 83d44a48d6dfa..a6ec5299b3241 100644 +--- a/components/cbor/reader_unittest.cc ++++ b/components/cbor/reader_unittest.cc +@@ -1451,5 +1451,42 @@ TEST(CBORReaderTest, AllowInvalidUTF8) { + EXPECT_FALSE(cbor); + EXPECT_EQ(Reader::DecoderError::INVALID_UTF8, error); + } ++TEST(CBORReaderTest, RejectsTagUnderDefaultConfig) { ++ static const uint8_t kTaggedCbor[] = { ++ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x71, 0x12, 0x20, 0x69, 0xea, 0x07, ++ 0x40, 0xf9, 0x80, 0x7a, 0x28, 0xf4, 0xd9, 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, 0x07, 0x2c, 0x90, 0x26, 0x6a, 0xb3, 0xe7, ++ 0x9d, 0xf6, 0x3a, 0x36, 0x5b ++ }; ++ Reader::Config config; ++ absl::optional cbor = Reader::Read(kTaggedCbor, config); ++ EXPECT_FALSE(cbor.has_value()); ++} ++TEST(CBORReaderTest, ReadsTagWhenConfiguredToDoSo) { ++ static const uint8_t kTaggedCbor[] = { ++ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x71, 0x12, 0x20, 0x69, 0xea, 0x07, ++ 0x40, 0xf9, 0x80, 0x7a, 0x28, 0xf4, 0xd9, 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, 0x07, 0x2c, 0x90, 0x26, 0x6a, 0xb3, 0xe7, ++ 0x9d, 0xf6, 0x3a, 0x36, 0x5b ++ }; ++ Reader::Config config; ++ config.parse_tags = true; ++ absl::optional cbor = Reader::Read(kTaggedCbor, config); ++ EXPECT_TRUE(cbor.has_value()); ++ auto& v = cbor.value(); ++ EXPECT_TRUE(v.has_tag()); ++ EXPECT_EQ(v.GetTag(),42UL); ++ EXPECT_TRUE(v.is_bytestring()); ++ EXPECT_EQ(v.type(), Value::Type::BYTE_STRING); ++ auto& bytes = v.GetBytestring(); ++ EXPECT_EQ(bytes.size(), 37UL); ++ EXPECT_EQ(bytes.at(0), 0x00);//identity multibase (e.g. not base-encoded, bytes are themselves) ++ EXPECT_EQ(bytes.at(1), 0x01);//CID version 1 ++ EXPECT_EQ(bytes.at(2), 0x71);//codec = dag-cbor ++ EXPECT_EQ(bytes.at(3), 0x12);//multihash = 18 = sha2-256 ++ EXPECT_EQ(bytes.at(4), 0x20);//hash length = 32 bytes ++ EXPECT_EQ(bytes.at(5), 0x69);//first byte of hash digest ++ EXPECT_EQ(bytes.at(36),0x5b);//last byte of hash digest ++} + + } // namespace cbor diff --git a/chromium_edits/122.0.6194.0/components/cbor/values.cc.patch b/chromium_edits/122.0.6194.0/components/cbor/values.cc.patch new file mode 100644 index 00000000..ddbab2b3 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/values.cc.patch @@ -0,0 +1,145 @@ +diff --git a/components/cbor/values.cc b/components/cbor/values.cc +index 02498209c820e..34055aef24cfe 100644 +--- a/components/cbor/values.cc ++++ b/components/cbor/values.cc +@@ -66,32 +66,34 @@ Value::Value(Type type) : type_(type) { + NOTREACHED(); + } + +-Value::Value(SimpleValue in_simple) +- : type_(Type::SIMPLE_VALUE), simple_value_(in_simple) { ++Value::Value(SimpleValue in_simple, uint64_t tag) ++ : type_(Type::SIMPLE_VALUE), simple_value_(in_simple), tag_(tag) { + CHECK(static_cast(in_simple) >= 20 && static_cast(in_simple) <= 23); + } + +-Value::Value(bool boolean_value) : type_(Type::SIMPLE_VALUE) { ++Value::Value(bool boolean_value, uint64_t tag) : type_(Type::SIMPLE_VALUE), tag_(tag) { + simple_value_ = boolean_value ? Value::SimpleValue::TRUE_VALUE + : Value::SimpleValue::FALSE_VALUE; + } + +-Value::Value(double float_value) +- : type_(Type::FLOAT_VALUE), float_value_(float_value) {} ++Value::Value(double float_value, uint64_t tag) ++ : type_(Type::FLOAT_VALUE), float_value_(float_value), tag_(tag) {} + +-Value::Value(int integer_value) +- : Value(base::checked_cast(integer_value)) {} ++Value::Value(int integer_value, uint64_t tag) ++ : Value(base::checked_cast(integer_value), tag) {} + +-Value::Value(int64_t integer_value) : integer_value_(integer_value) { ++Value::Value(int64_t integer_value, uint64_t tag) : integer_value_(integer_value), tag_(tag) { + type_ = integer_value >= 0 ? Type::UNSIGNED : Type::NEGATIVE; + } + +-Value::Value(base::span in_bytes) ++Value::Value(base::span in_bytes, uint64_t tag) + : type_(Type::BYTE_STRING), +- bytestring_value_(in_bytes.begin(), in_bytes.end()) {} ++ bytestring_value_(in_bytes.begin(), in_bytes.end()), ++ tag_(tag) ++ {} + +-Value::Value(base::span in_bytes, Type type) +- : type_(type), bytestring_value_(in_bytes.begin(), in_bytes.end()) { ++Value::Value(base::span in_bytes, Type type, uint64_t tag) ++ : type_(type), bytestring_value_(in_bytes.begin(), in_bytes.end()), tag_(tag) { + DCHECK(type_ == Type::BYTE_STRING || type_ == Type::INVALID_UTF8); + } + +@@ -117,7 +119,8 @@ Value::Value(std::string&& in_string, Type type) noexcept : type_(type) { + } + } + +-Value::Value(base::StringPiece in_string, Type type) : type_(type) { ++Value::Value(base::StringPiece in_string, Type type, uint64_t tag) ++: type_(type), tag_(tag) { + switch (type_) { + case Type::STRING: + new (&string_value_) std::string(); +@@ -133,16 +136,18 @@ Value::Value(base::StringPiece in_string, Type type) : type_(type) { + } + } + +-Value::Value(const ArrayValue& in_array) : type_(Type::ARRAY), array_value_() { ++Value::Value(const ArrayValue& in_array, uint64_t tag) ++: type_(Type::ARRAY), array_value_(), tag_(tag) { + array_value_.reserve(in_array.size()); + for (const auto& val : in_array) + array_value_.emplace_back(val.Clone()); + } + +-Value::Value(ArrayValue&& in_array) noexcept +- : type_(Type::ARRAY), array_value_(std::move(in_array)) {} ++Value::Value(ArrayValue&& in_array, uint64_t tag) noexcept ++ : type_(Type::ARRAY), array_value_(std::move(in_array)), tag_(tag) {} + +-Value::Value(const MapValue& in_map) : type_(Type::MAP), map_value_() { ++Value::Value(const MapValue& in_map, uint64_t tag) ++: type_(Type::MAP), map_value_(), tag_(tag) { + map_value_.reserve(in_map.size()); + for (const auto& it : in_map) + map_value_.emplace_hint(map_value_.end(), it.first.Clone(), +@@ -168,31 +173,36 @@ Value Value::Clone() const { + case Type::NONE: + return Value(); + case Type::INVALID_UTF8: +- return Value(bytestring_value_, Type::INVALID_UTF8); ++ return Value(bytestring_value_, Type::INVALID_UTF8, tag_); + case Type::UNSIGNED: + case Type::NEGATIVE: +- return Value(integer_value_); ++ return Value(integer_value_, tag_); + case Type::BYTE_STRING: +- return Value(bytestring_value_); ++ return Value(bytestring_value_, tag_); + case Type::STRING: +- return Value(string_value_); ++ return Value(string_value_, Type::STRING, tag_); + case Type::ARRAY: +- return Value(array_value_); ++ return Value(array_value_, tag_); + case Type::MAP: +- return Value(map_value_); ++ return Value(map_value_, tag_); + case Type::TAG: + NOTREACHED() << constants::kUnsupportedMajorType; + return Value(); + case Type::SIMPLE_VALUE: +- return Value(simple_value_); ++ return Value(simple_value_, tag_); + case Type::FLOAT_VALUE: +- return Value(float_value_); ++ return Value(float_value_, tag_); + } + + NOTREACHED(); + return Value(); + } + ++Value& Value::SetTag(uint64_t tag) noexcept { ++ tag_ = tag; ++ return *this; ++} ++ + Value::SimpleValue Value::GetSimpleValue() const { + CHECK(is_simple()); + return simple_value_; +@@ -258,9 +268,14 @@ const Value::BinaryValue& Value::GetInvalidUTF8() const { + return bytestring_value_; + } + ++uint64_t Value::GetTag() const { ++ CHECK(has_tag()); ++ return tag_; ++} ++ + void Value::InternalMoveConstructFrom(Value&& that) { + type_ = that.type_; +- ++ tag_ = that.tag_; + switch (type_) { + case Type::UNSIGNED: + case Type::NEGATIVE: diff --git a/chromium_edits/122.0.6194.0/components/cbor/values.h.patch b/chromium_edits/122.0.6194.0/components/cbor/values.h.patch new file mode 100644 index 00000000..ca39df01 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/values.h.patch @@ -0,0 +1,79 @@ +diff --git a/components/cbor/values.h b/components/cbor/values.h +index d81ef5607c55a..10216a8dcdc57 100644 +--- a/components/cbor/values.h ++++ b/components/cbor/values.h +@@ -127,28 +127,29 @@ class CBOR_EXPORT Value { + + explicit Value(Type type); + +- explicit Value(SimpleValue in_simple); +- explicit Value(bool boolean_value); +- explicit Value(double in_float); ++ explicit Value(SimpleValue in_simple, uint64_t tag = NO_TAG); ++ explicit Value(bool boolean_value, uint64_t tag = NO_TAG); ++ explicit Value(double in_float, uint64_t tag = NO_TAG); + +- explicit Value(int integer_value); +- explicit Value(int64_t integer_value); ++ explicit Value(int integer_value, uint64_t tag = NO_TAG); ++ explicit Value(int64_t integer_value, uint64_t tag = NO_TAG); + explicit Value(uint64_t integer_value) = delete; + +- explicit Value(base::span in_bytes); ++ explicit Value(base::span in_bytes, uint64_t tag = NO_TAG); + explicit Value(BinaryValue&& in_bytes) noexcept; + + explicit Value(const char* in_string, Type type = Type::STRING); + explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept; +- explicit Value(base::StringPiece in_string, Type type = Type::STRING); ++ explicit Value(base::StringPiece in_string, Type type = Type::STRING, uint64_t tag = NO_TAG); + +- explicit Value(const ArrayValue& in_array); +- explicit Value(ArrayValue&& in_array) noexcept; ++ explicit Value(const ArrayValue& in_array, uint64_t tag = NO_TAG); ++ explicit Value(ArrayValue&& in_array, uint64_t tag = NO_TAG) noexcept; + +- explicit Value(const MapValue& in_map); ++ explicit Value(const MapValue& in_map, uint64_t tag = NO_TAG); + explicit Value(MapValue&& in_map) noexcept; + + Value& operator=(Value&& that) noexcept; ++ Value& SetTag(uint64_t) noexcept; + + Value(const Value&) = delete; + Value& operator=(const Value&) = delete; +@@ -179,6 +180,7 @@ class CBOR_EXPORT Value { + bool is_string() const { return type() == Type::STRING; } + bool is_array() const { return type() == Type::ARRAY; } + bool is_map() const { return type() == Type::MAP; } ++ bool has_tag() const { return tag_ != NO_TAG; } + + // These will all fatally assert if the type doesn't match. + SimpleValue GetSimpleValue() const; +@@ -194,12 +196,13 @@ class CBOR_EXPORT Value { + const ArrayValue& GetArray() const; + const MapValue& GetMap() const; + const BinaryValue& GetInvalidUTF8() const; ++ uint64_t GetTag() const; + + private: + friend class Reader; + // This constructor allows INVALID_UTF8 values to be created, which only + // |Reader| and InvalidUTF8StringValueForTesting() may do. +- Value(base::span in_bytes, Type type); ++ Value(base::span in_bytes, Type type, uint64_t tag = NO_TAG); + + Type type_; + +@@ -213,6 +216,11 @@ class CBOR_EXPORT Value { + MapValue map_value_; + }; + ++ //This value specified as Invalid, ++ // used here to represent absence of TAG ++ constexpr static uint64_t NO_TAG = 0xFFFF; ++ uint64_t tag_ = NO_TAG; ++ + void InternalMoveConstructFrom(Value&& that); + void InternalCleanup(); + }; diff --git a/chromium_edits/122.0.6194.0/components/cbor/writer.cc.patch b/chromium_edits/122.0.6194.0/components/cbor/writer.cc.patch new file mode 100644 index 00000000..21fe28ce --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/writer.cc.patch @@ -0,0 +1,14 @@ +diff --git a/components/cbor/writer.cc b/components/cbor/writer.cc +index bb22754d36a07..aae4027836377 100644 +--- a/components/cbor/writer.cc ++++ b/components/cbor/writer.cc +@@ -47,6 +47,9 @@ bool Writer::EncodeCBOR(const Value& node, + if (max_nesting_level < 0) + return false; + ++ if (node.has_tag()) { ++ StartItem(Value::Type::TAG, node.GetTag()); ++ } + switch (node.type()) { + case Value::Type::NONE: { + StartItem(Value::Type::BYTE_STRING, 0); diff --git a/chromium_edits/122.0.6194.0/components/cbor/writer_unittest.cc.patch b/chromium_edits/122.0.6194.0/components/cbor/writer_unittest.cc.patch new file mode 100644 index 00000000..240fee83 --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/cbor/writer_unittest.cc.patch @@ -0,0 +1,36 @@ +diff --git a/components/cbor/writer_unittest.cc b/components/cbor/writer_unittest.cc +index e3bffe20734bc..0ed569ae164a0 100644 +--- a/components/cbor/writer_unittest.cc ++++ b/components/cbor/writer_unittest.cc +@@ -522,4 +522,31 @@ TEST(CBORWriterTest, OverlyNestedCBOR) { + EXPECT_FALSE(Writer::Write(Value(map), 4).has_value()); + } + ++TEST(CBORWriterTest, CanWriteTag) { ++ std::array content{ ++ 0x00, 0x01, 0x71, 0x12, 0x20, ++ 0x69, 0xea, 0x07, 0x40, 0xf9, ++ 0x80, 0x7a, 0x28, 0xf4, 0xd9, ++ 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, ++ 0x07, 0x2c, 0x90, 0x26, 0x6a, ++ 0xb3, 0xe7, 0x9d, 0xf6, 0x3a, ++ 0x36, 0x5b ++ }; ++ Value to_write(content); ++ to_write.SetTag(42); ++ auto result = Writer::Write(to_write); ++ EXPECT_TRUE(result.has_value()); ++ auto& bytes = result.value(); ++ EXPECT_EQ(bytes.size(), 41UL); ++ EXPECT_EQ(bytes.at(0), 0xd8); ++ EXPECT_EQ(bytes.at(1), 0x2a); ++ EXPECT_EQ(bytes.at(2), 0x58); ++ EXPECT_EQ(bytes.at(3), 0x25); ++ for (auto i = 0UL; i < content.size(); ++i) { ++ ASSERT_LT(i + 4UL, bytes.size()); ++ ASSERT_EQ(content.at(i), bytes.at(i+4UL)); ++ } ++} ++ + } // namespace cbor diff --git a/chromium_edits/122.0.6194.0/components/open_from_clipboard/clipboard_recent_content_generic.cc.patch b/chromium_edits/122.0.6194.0/components/open_from_clipboard/clipboard_recent_content_generic.cc.patch new file mode 100644 index 00000000..891b53df --- /dev/null +++ b/chromium_edits/122.0.6194.0/components/open_from_clipboard/clipboard_recent_content_generic.cc.patch @@ -0,0 +1,13 @@ +diff --git a/components/open_from_clipboard/clipboard_recent_content_generic.cc b/components/open_from_clipboard/clipboard_recent_content_generic.cc +index 4dcafecbc66c6..d205209c08162 100644 +--- a/components/open_from_clipboard/clipboard_recent_content_generic.cc ++++ b/components/open_from_clipboard/clipboard_recent_content_generic.cc +@@ -20,7 +20,7 @@ + namespace { + // Schemes appropriate for suggestion by ClipboardRecentContent. + const char* kAuthorizedSchemes[] = { +- url::kAboutScheme, url::kDataScheme, url::kHttpScheme, url::kHttpsScheme, ++ url::kAboutScheme, url::kDataScheme, url::kHttpScheme, url::kHttpsScheme, "ipfs", "ipns" + // TODO(mpearson): add support for chrome:// URLs. Right now the scheme + // for that lives in content and is accessible via + // GetEmbedderRepresentationOfAboutScheme() or content::kChromeUIScheme diff --git a/chromium_edits/122.0.6194.0/net/dns/dns_config_service_linux.cc.patch b/chromium_edits/122.0.6194.0/net/dns/dns_config_service_linux.cc.patch new file mode 100644 index 00000000..a5e9863f --- /dev/null +++ b/chromium_edits/122.0.6194.0/net/dns/dns_config_service_linux.cc.patch @@ -0,0 +1,18 @@ +diff --git a/net/dns/dns_config_service_linux.cc b/net/dns/dns_config_service_linux.cc +index 5273da5190277..12b28b86a4c00 100644 +--- a/net/dns/dns_config_service_linux.cc ++++ b/net/dns/dns_config_service_linux.cc +@@ -272,11 +272,11 @@ bool IsNsswitchConfigCompatible( + // Ignore any entries after `kDns` because Chrome will fallback to the + // system resolver if a result was not found in DNS. + return true; +- ++ case NsswitchReader::Service::kResolve: ++ break; + case NsswitchReader::Service::kMdns: + case NsswitchReader::Service::kMdns4: + case NsswitchReader::Service::kMdns6: +- case NsswitchReader::Service::kResolve: + case NsswitchReader::Service::kNis: + RecordIncompatibleNsswitchReason( + IncompatibleNsswitchReason::kIncompatibleService, diff --git a/chromium_edits/122.0.6194.0/third_party/blink/renderer/platform/weborigin/scheme_registry.cc.patch b/chromium_edits/122.0.6194.0/third_party/blink/renderer/platform/weborigin/scheme_registry.cc.patch new file mode 100644 index 00000000..119d72b2 --- /dev/null +++ b/chromium_edits/122.0.6194.0/third_party/blink/renderer/platform/weborigin/scheme_registry.cc.patch @@ -0,0 +1,13 @@ +diff --git a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc +index 4eadf46ea0c24..d62fc7fb14e01 100644 +--- a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc ++++ b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc +@@ -67,7 +67,7 @@ class URLSchemesRegistry final { + // is considered secure. Additional checks are performed to ensure that + // other http pages are filtered out. + service_worker_schemes({"http", "https"}), +- fetch_api_schemes({"http", "https"}), ++ fetch_api_schemes({"http", "https", "ipfs", "ipns"}), + allowed_in_referrer_schemes({"http", "https"}) { + for (auto& scheme : url::GetCorsEnabledSchemes()) + cors_enabled_schemes.insert(scheme.c_str()); diff --git a/chromium_edits/122.0.6194.0/url/BUILD.gn.patch b/chromium_edits/122.0.6194.0/url/BUILD.gn.patch new file mode 100644 index 00000000..293eb89e --- /dev/null +++ b/chromium_edits/122.0.6194.0/url/BUILD.gn.patch @@ -0,0 +1,32 @@ +diff --git a/url/BUILD.gn b/url/BUILD.gn +index 0ac17c08dc5bc..2497d02658bb3 100644 +--- a/url/BUILD.gn ++++ b/url/BUILD.gn +@@ -5,6 +5,7 @@ + import("//build/buildflag_header.gni") + import("//testing/libfuzzer/fuzzer_test.gni") + import("//testing/test.gni") ++import("//third_party/ipfs_client/args.gni") + import("features.gni") + + import("//build/config/cronet/config.gni") +@@ -68,6 +69,7 @@ component("url") { + public_deps = [ + "//base", + "//build:robolectric_buildflags", ++ "//third_party/ipfs_client:ipfs_buildflags", + ] + + configs += [ "//build/config/compiler:wexit_time_destructors" ] +@@ -90,6 +92,11 @@ component("url") { + public_configs = [ "//third_party/jdk" ] + } + ++ if (enable_ipfs) { ++ sources += [ "url_canon_ipfs.cc" ] ++ deps += [ "//third_party/ipfs_client:ipfs_client" ] ++ } ++ + if (is_win) { + # Don't conflict with Windows' "url.dll". + output_name = "url_lib" diff --git a/chromium_edits/122.0.6194.0/url/url_canon.h.patch b/chromium_edits/122.0.6194.0/url/url_canon.h.patch new file mode 100644 index 00000000..7ffd3a2f --- /dev/null +++ b/chromium_edits/122.0.6194.0/url/url_canon.h.patch @@ -0,0 +1,28 @@ +diff --git a/url/url_canon.h b/url/url_canon.h +index 8c48f9825d8cf..b9ad961e1b123 100644 +--- a/url/url_canon.h ++++ b/url/url_canon.h +@@ -804,6 +804,23 @@ bool CanonicalizeMailtoURL(const char16_t* spec, + CanonOutput* output, + Parsed* new_parsed); + ++COMPONENT_EXPORT(URL) ++bool CanonicalizeIpfsURL(const char* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* query_converter, ++ CanonOutput* output, ++ Parsed* new_parsed); ++COMPONENT_EXPORT(URL) ++bool CanonicalizeIpfsURL(const char16_t* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* query_converter, ++ CanonOutput* output, ++ Parsed* new_parsed); ++ + // Part replacer -------------------------------------------------------------- + + // Internal structure used for storing separate strings for each component. diff --git a/chromium_edits/122.0.6194.0/url/url_canon_ipfs.cc b/chromium_edits/122.0.6194.0/url/url_canon_ipfs.cc new file mode 100644 index 00000000..d7c9fdc7 --- /dev/null +++ b/chromium_edits/122.0.6194.0/url/url_canon_ipfs.cc @@ -0,0 +1,55 @@ +#include "url_canon_internal.h" + +#include +#include + +#include + +bool url::CanonicalizeIpfsURL(const char* spec, + int spec_len, + const Parsed& parsed, + SchemeType scheme_type, + CharsetConverter* charset_converter, + CanonOutput* output, + Parsed* output_parsed) { + if ( spec_len < 1 || !spec ) { + return false; + } + if ( parsed.host.len < 1 ) { + return false; + } + std::string_view cid_str{ spec + parsed.host.begin, static_cast(parsed.host.len) }; + auto cid = ipfs::Cid(cid_str); + if ( !cid.valid() ) { + cid = ipfs::id_cid::forText( std::string{cid_str} + " is not a valid CID." ); + } + auto as_str = cid.to_string(); + if ( as_str.empty() ) { + return false; + } + std::string stdurl{ spec, static_cast(parsed.host.begin) }; + stdurl.append( as_str ); + stdurl.append( spec + parsed.host.end(), spec_len - parsed.host.end() ); + spec = stdurl.data(); + spec_len = static_cast(stdurl.size()); + Parsed parsed_input; + ParseStandardURL(spec, spec_len, &parsed_input); + return CanonicalizeStandardURL( + spec, + parsed_input, + scheme_type, + charset_converter, + output, output_parsed + ); +} +bool url::CanonicalizeIpfsURL(const char16_t* spec, + int spec_len, + const Parsed& parsed, + SchemeType scheme_type, + CharsetConverter* query_converter, + CanonOutput* output, + Parsed* new_parsed) { + RawCanonOutput<2048> as8; + ConvertUTF16ToUTF8(spec, spec_len, &as8); + return CanonicalizeIpfsURL(as8.data(), as8.length(), parsed, scheme_type, query_converter, output, new_parsed); +} diff --git a/chromium_edits/122.0.6194.0/url/url_util.cc.patch b/chromium_edits/122.0.6194.0/url/url_util.cc.patch new file mode 100644 index 00000000..814f4b82 --- /dev/null +++ b/chromium_edits/122.0.6194.0/url/url_util.cc.patch @@ -0,0 +1,22 @@ +diff --git a/url/url_util.cc b/url/url_util.cc +index 6f83f33c01c6b..a248e11c49445 100644 +--- a/url/url_util.cc ++++ b/url/url_util.cc +@@ -273,8 +273,15 @@ bool DoCanonicalize(const CHAR* spec, + } else if (DoCompareSchemeComponent(spec, scheme, url::kFileSystemScheme)) { + // Filesystem URLs are special. + ParseFileSystemURL(spec, spec_len, &parsed_input); +- success = CanonicalizeFileSystemURL(spec, parsed_input, charset_converter, +- output, output_parsed); ++ success = CanonicalizeFileSystemURL(spec, parsed_input, ++ charset_converter, output, ++ output_parsed); ++ ++ } else if (DoCompareSchemeComponent(spec, scheme, "ipfs")) { ++ // Switch multibase away from case-sensitive ones before continuing canonicalization. ++ ParseStandardURL(spec, spec_len, &parsed_input); ++ success = CanonicalizeIpfsURL(spec, spec_len, parsed_input, scheme_type, ++ charset_converter, output, output_parsed); + + } else if (DoIsStandard(spec, scheme, &scheme_type)) { + // All "normal" URLs. diff --git a/cmake/chromium.py b/cmake/chromium.py index 0cd38b36..f3dfc84e 100755 --- a/cmake/chromium.py +++ b/cmake/chromium.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 +from verbose import verbose from cache_vars import build_dir, vars from patch import Patcher -from verbose import verbose from glob import glob from os import environ, makedirs, remove @@ -115,13 +115,7 @@ def runpy(args, silent=False): if not isfile(join(src, '.landmines')): run([python, join(depot_tools_dir, 'gclient.py'), 'runhooks', '-j', jobs]) -with open(join(src, 'chrome', 'browser', 'BUILD.gn')) as w: - content = w.read() - if 'components/ipfs' in content: - verbose('Chromium seems to be already patched.') - else: - print('Apply patch file...', file=stderr) - patcher.apply() +patcher.apply() ipfs_dir = join(src, 'components', 'ipfs') diff --git a/cmake/patch.py b/cmake/patch.py index f310fcee..2bf78f3f 100755 --- a/cmake/patch.py +++ b/cmake/patch.py @@ -118,36 +118,51 @@ def apply(self): if d < win_dist or (d == win_dist and len(ref) < len(win)): win_dist = d win = ref - print('Best patch file is', win, file=stderr) - edits_dir = join(self.edir, 'win') - for edit in glob(f'{edits_dir}/**/*', recursive=True): + edits_dir = join(self.edir, win) + edit_glob = f'{edits_dir}/**/*' + print('Best edits version is', win, 'look for edits by', edit_glob, file=stderr) + for edit in glob(edit_glob, recursive=True): if not isfile(edit): continue + verbose('Have edit:', edit) ext = splitext(edit)[1] rel = relpath(edit, edits_dir) to_path = join(self.csrc, rel) if ext == '.patch': - check_patch(edit, rel, to_path) + self.check_patch(edit, rel, to_path) elif ext == '.rm': if isfile(to_path): print("Remove", to_path, 'due to', edit) remove(to_path) else: verbose(f"{to_path} already removed") - elif content_differs(edit, to_path): + elif not isfile(to_path): print('Copy', edit, '->', to_path) + copyfile(edit, to_path) + elif content_differs(edit, to_path): + print('Warning:', to_path, 'exists, is different from ', edit, ' and is not being overwritten.') else: verbose(f"{to_path} already copied") + verbose('Done patching') def check_patch(self, patch_path: str, relative: str, target_path: str): if 0 == self.git(['apply', '--check', '--reverse', '--verbose', patch_path], Result.ExitCode): verbose(patch_path, 'already applied.') return - print("Will patch file", relative) - #TODO - self.git(['apply', '--check', '--reverse', '--verbose', patch_path], Result.OrDie) - + src = splitext(relative)[0] + ec = self.git(['apply', '--verbose', patch_path], Result.ExitCode) + verbose('Applying patch', patch_path, 'gave exit code', ec) + if ec == 0: + print('Patched', src, 'with', patch_path) + else: + with open(join(self.csrc,src)) as target_file: + text = target_file.read() + if 'ipfs' in text: + verbose("Patch file", patch_path, 'may have already been applied.') + else: + print("Failed to patch", src, '( at', join(self.csrc,src), ') with', patch_path) + exit(8) def git(self, args: list[str], result: Result) -> str: a = [self.gbin, '-C', self.csrc] + args @@ -240,7 +255,7 @@ def electron_version(self, branch='main'): def unavailable(self): avail = list(map(as_int, self.available())) version_set = {} - fudge = 59888 + fudge = 59891 def check(version, version_set, s): i = as_int(version) by = (fudge,0) diff --git a/component/chromium_ipfs_context.cc b/component/chromium_ipfs_context.cc index 92a56994..7ef6ad8f 100644 --- a/component/chromium_ipfs_context.cc +++ b/component/chromium_ipfs_context.cc @@ -89,8 +89,7 @@ bool Self::VerifyKeySignature(SigningKeyType t, ByteView signature, ByteView data, ByteView key_bytes) const { - return crypto_api::VerifySignature(static_cast(t), signature, - data, key_bytes); + return crypto_api::VerifySignature(t, signature, data, key_bytes); } auto Self::ParseCbor(ipfs::ContextApi::ByteView bytes) const -> std::unique_ptr { diff --git a/component/crypto_api.cc b/component/crypto_api.cc index d15a63f1..250c9024 100644 --- a/component/crypto_api.cc +++ b/component/crypto_api.cc @@ -7,17 +7,17 @@ #include "third_party/boringssl/src/include/openssl/evp.h" namespace { -int ToEvpKeyType(ipfs::ipns::KeyType t) { - using ipfs::ipns::KeyType; +int ToEvpKeyType(ipfs::ContextApi::SigningKeyType t) { + using T = ipfs::ContextApi::SigningKeyType; switch (t) { - case KeyType::ECDSA: + case T::ECDSA: LOG(ERROR) << "TODO Check on ECDSA key type translation."; return EVP_PKEY_EC; - case KeyType::Ed25519: + case T::Ed25519: return EVP_PKEY_ED25519; - case KeyType::RSA: + case T::RSA: return EVP_PKEY_RSA; - case KeyType::Secp256k1: + case T::Secp256k1: LOG(ERROR) << "TODO Check on Secp256k1 key type translation."; return EVP_PKEY_DSA; default: @@ -29,7 +29,7 @@ int ToEvpKeyType(ipfs::ipns::KeyType t) { namespace cpto = ipfs::crypto_api; -bool cpto::VerifySignature(ipfs::ipns::KeyType key_type, +bool cpto::VerifySignature(ipfs::ContextApi::SigningKeyType key_type, ipfs::ByteView signature, ipfs::ByteView data, ipfs::ByteView key_bytes) { diff --git a/component/crypto_api.h b/component/crypto_api.h index 1363bb1f..3b3861e1 100644 --- a/component/crypto_api.h +++ b/component/crypto_api.h @@ -1,22 +1,17 @@ #ifndef IPFS_VALIDATE_SIGNATURE_H_ #define IPFS_VALIDATE_SIGNATURE_H_ -#include "components/webcrypto/algorithm_implementation.h" - -#include "third_party/ipfs_client/keys.pb.h" - +#include #include +#include "components/webcrypto/algorithm_implementation.h" namespace ipfs::crypto_api { -/* -using Algo = std::pair>; -Algo GetAlgo(ipfs::ipns::KeyType); -*/ -bool VerifySignature(ipfs::ipns::KeyType, + +bool VerifySignature(ipfs::ContextApi::SigningKeyType, ByteView signature, ByteView data, ByteView key); + } // namespace ipfs::crypto_api #endif // IPFS_VALIDATE_SIGNATURE_H_ diff --git a/component/patches/122.0.6194.0.patch b/component/patches/122.0.6194.0.patch new file mode 100644 index 00000000..2639e189 --- /dev/null +++ b/component/patches/122.0.6194.0.patch @@ -0,0 +1,880 @@ +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +index ea574b1863e18..7239008b4e215 100644 +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -39,6 +39,7 @@ import("//rlz/buildflags/buildflags.gni") + import("//sandbox/features.gni") + import("//testing/libfuzzer/fuzzer_test.gni") + import("//third_party/blink/public/public_features.gni") ++import("//third_party/ipfs_client/args.gni") + import("//third_party/protobuf/proto_library.gni") + import("//third_party/webrtc/webrtc.gni") + import("//third_party/widevine/cdm/widevine.gni") +@@ -2615,6 +2616,14 @@ static_library("browser") { + ] + } + ++ if (enable_ipfs) { ++ sources += [ ++ "ipfs_extra_parts.cc", ++ "ipfs_extra_parts.h", ++ ] ++ deps += [ "//components/ipfs" ] ++ } ++ + if (is_chromeos_ash) { + deps += [ "//chrome/browser/screen_ai:screen_ai_dlc_installer" ] + } +diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc +index b076446400486..2b2f2724d3b75 100644 +--- a/chrome/browser/about_flags.cc ++++ b/chrome/browser/about_flags.cc +@@ -214,6 +214,7 @@ + #include "third_party/blink/public/common/features_generated.h" + #include "third_party/blink/public/common/forcedark/forcedark_switches.h" + #include "third_party/blink/public/common/switches.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + #include "ui/accessibility/accessibility_features.h" + #include "ui/accessibility/accessibility_switches.h" + #include "ui/base/ozone_buildflags.h" +@@ -310,6 +311,10 @@ + #include "extensions/common/switches.h" + #endif // BUILDFLAG(ENABLE_EXTENSIONS) + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#endif ++ + #if BUILDFLAG(ENABLE_PDF) + #include "pdf/pdf_features.h" + #endif +@@ -9459,6 +9464,14 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kOmitCorsClientCertDescription, kOsAll, + FEATURE_VALUE_TYPE(network::features::kOmitCorsClientCert)}, + ++#if BUILDFLAG(ENABLE_IPFS) ++ {"enable-ipfs", ++ flag_descriptions::kEnableIpfsName, ++ flag_descriptions::kEnableIpfsDescription, ++ kOsMac | kOsWin | kOsLinux,//TODO: These are the only variants currently getting built, but that is not likely to remain the case ++ FEATURE_VALUE_TYPE(ipfs::kEnableIpfs)}, ++#endif ++ + {"use-idna2008-non-transitional", + flag_descriptions::kUseIDNA2008NonTransitionalName, + flag_descriptions::kUseIDNA2008NonTransitionalDescription, kOsAll, +diff --git a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc +index 4c88614c68c25..f8bb12a3b0c2e 100644 +--- a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc ++++ b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc +@@ -10,6 +10,8 @@ + #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" + #include "chrome/browser/external_protocol/external_protocol_handler.h" + #include "chrome/browser/profiles/profile.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" ++ + #if BUILDFLAG(IS_ANDROID) + #include "chrome/browser/profiles/profile_android.h" + #endif +@@ -18,6 +20,9 @@ + #include "chrome/browser/ui/android/omnibox/jni_headers/ChromeAutocompleteSchemeClassifier_jni.h" + #endif + #include "components/custom_handlers/protocol_handler_registry.h" ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#endif + #include "content/public/common/url_constants.h" + #include "url/url_util.h" + +@@ -55,12 +60,20 @@ ChromeAutocompleteSchemeClassifier::GetInputTypeForScheme( + if (scheme.empty()) { + return metrics::OmniboxInputType::EMPTY; + } +- if (base::IsStringASCII(scheme) && +- (ProfileIOData::IsHandledProtocol(scheme) || +- base::EqualsCaseInsensitiveASCII(scheme, content::kViewSourceScheme) || +- base::EqualsCaseInsensitiveASCII(scheme, url::kJavaScriptScheme) || +- base::EqualsCaseInsensitiveASCII(scheme, url::kDataScheme))) { +- return metrics::OmniboxInputType::URL; ++ if (base::IsStringASCII(scheme)) { ++ if (ProfileIOData::IsHandledProtocol(scheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, content::kViewSourceScheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, url::kJavaScriptScheme) || ++ base::EqualsCaseInsensitiveASCII(scheme, url::kDataScheme)) { ++ return metrics::OmniboxInputType::URL; ++ } ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs) && ++ (base::EqualsCaseInsensitiveASCII(scheme, "ipfs") || base::EqualsCaseInsensitiveASCII(scheme, "ipns")) ++ ) { ++ return metrics::OmniboxInputType::URL; ++ } ++#endif + } + + // Also check for schemes registered via registerProtocolHandler(), which +diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc +index 667370e623970..c09550c753e8e 100644 +--- a/chrome/browser/chrome_content_browser_client.cc ++++ b/chrome/browser/chrome_content_browser_client.cc +@@ -377,6 +377,7 @@ + #include "third_party/blink/public/common/switches.h" + #include "third_party/blink/public/mojom/browsing_topics/browsing_topics.mojom.h" + #include "third_party/blink/public/public_buildflags.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + #include "third_party/widevine/cdm/buildflags.h" + #include "ui/base/clipboard/clipboard_format_type.h" + #include "ui/base/l10n/l10n_util.h" +@@ -499,6 +500,13 @@ + #include "chrome/browser/fuchsia/chrome_browser_main_parts_fuchsia.h" + #endif + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "chrome/browser/ipfs_extra_parts.h" ++#include "components/ipfs/interceptor.h" ++#include "components/ipfs/ipfs_features.h" ++#include "components/ipfs/url_loader_factory.h" ++#endif ++ + #if BUILDFLAG(IS_CHROMEOS) + #include "base/debug/leak_annotations.h" + #include "chrome/browser/apps/app_service/app_install/app_install_navigation_throttle.h" +@@ -1711,6 +1719,11 @@ ChromeContentBrowserClient::CreateBrowserMainParts(bool is_integration_test) { + main_parts->AddParts( + std::make_unique()); + ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ main_parts->AddParts(std::make_unique()); ++ } ++#endif + return main_parts; + } + +@@ -6075,12 +6088,25 @@ void ChromeContentBrowserClient:: + const absl::optional& request_initiator_origin, + NonNetworkURLLoaderFactoryMap* factories) { + #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(ENABLE_EXTENSIONS) || \ +- !BUILDFLAG(IS_ANDROID) ++ !BUILDFLAG(IS_ANDROID) || BUILDFLAG(ENABLE_IPFS) + content::RenderFrameHost* frame_host = + 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) ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ network::mojom::URLLoaderFactory* default_factory = g_browser_process->system_network_context_manager()->GetURLLoaderFactory(); ++ auto* context = web_contents->GetBrowserContext(); ++ ipfs::IpfsURLLoaderFactory::Create( ++ factories, ++ context, ++ default_factory, ++ GetSystemNetworkContext(), ++ Profile::FromBrowserContext(context)->GetPrefs() ++ ); ++ } ++#endif // BUILDFLAG(ENABLE_IPFS) + + #if BUILDFLAG(IS_CHROMEOS_ASH) + if (web_contents) { +@@ -6222,6 +6248,11 @@ ChromeContentBrowserClient::WillCreateURLLoaderRequestInterceptors( + scoped_refptr navigation_response_task_runner) { + std::vector> + interceptors; ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ interceptors.push_back(std::make_unique(g_browser_process->system_network_context_manager()->GetURLLoaderFactory(), GetSystemNetworkContext())); ++ } ++#endif + #if BUILDFLAG(ENABLE_OFFLINE_PAGES) + interceptors.push_back( + std::make_unique( +diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json +index 7a0c7c06f4e8e..8af9a104e1fe8 100644 +--- a/chrome/browser/flag-metadata.json ++++ b/chrome/browser/flag-metadata.json +@@ -2931,6 +2931,11 @@ + "owners": [ "hanxi@chromium.org", "wychen@chromium.org" ], + "expiry_milestone": 130 + }, ++ { ++ "name": "enable-ipfs", ++ "owners": [ "//components/ipfs/OWNERS" ], ++ "expiry_milestone": 150 ++ }, + { + "name": "enable-isolated-sandboxed-iframes", + "owners": [ "wjmaclean@chromium.org", "alexmos@chromium.org", "creis@chromium.org" ], +diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc +index b4f75320e4669..fc2ef00f6eb5c 100644 +--- a/chrome/browser/flag_descriptions.cc ++++ b/chrome/browser/flag_descriptions.cc +@@ -289,6 +289,11 @@ const char kEnableBenchmarkingDescription[] = + "after 3 restarts. On the third restart, the flag will appear to be off " + "but the effect is still active."; + ++#if BUILDFLAG(ENABLE_IPFS) ++extern const char kEnableIpfsName[] = "Enable IPFS"; ++extern const char kEnableIpfsDescription[] = "Enable ipfs:// and ipns:// URLs"; ++#endif ++ + const char kPreloadingOnPerformancePageName[] = + "Preloading Settings on Performance Page"; + const char kPreloadingOnPerformancePageDescription[] = +diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h +index 65b8bcb40770c..d5ae8dca53910 100644 +--- a/chrome/browser/flag_descriptions.h ++++ b/chrome/browser/flag_descriptions.h +@@ -23,6 +23,7 @@ + #include "pdf/buildflags.h" + #include "printing/buildflags/buildflags.h" + #include "third_party/blink/public/common/buildflags.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + + // This file declares strings used in chrome://flags. These messages are not + // translated, because instead of end-users they target Chromium developers and +@@ -179,6 +180,11 @@ extern const char kDownloadWarningImprovementsDescription[]; + extern const char kEnableBenchmarkingName[]; + extern const char kEnableBenchmarkingDescription[]; + ++#if BUILDFLAG(ENABLE_IPFS) ++extern const char kEnableIpfsName[]; ++extern const char kEnableIpfsDescription[]; ++#endif ++ + #if BUILDFLAG(USE_FONTATIONS_BACKEND) + extern const char kFontationsFontBackendName[]; + extern const char kFontationsFontBackendDescription[]; +diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc +index 86a09cfe49376..d8e166f76179e 100644 +--- a/chrome/browser/prefs/browser_prefs.cc ++++ b/chrome/browser/prefs/browser_prefs.cc +@@ -189,6 +189,7 @@ + #include "printing/buildflags/buildflags.h" + #include "rlz/buildflags/buildflags.h" + #include "third_party/abseil-cpp/absl/types/optional.h" ++#include "third_party/ipfs_client/ipfs_buildflags.h" + + #if BUILDFLAG(ENABLE_BACKGROUND_MODE) + #include "chrome/browser/background/background_mode_manager.h" +@@ -233,6 +234,11 @@ + #include "chrome/browser/pdf/pdf_pref_names.h" + #endif // BUILDFLAG(ENABLE_PDF) + ++#if BUILDFLAG(ENABLE_IPFS) ++#include "components/ipfs/ipfs_features.h" ++#include "components/ipfs/preferences.h" ++#endif ++ + #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + #include "chrome/browser/screen_ai/pref_names.h" + #endif +@@ -1678,6 +1684,11 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, + IncognitoModePrefs::RegisterProfilePrefs(registry); + invalidation::PerUserTopicSubscriptionManager::RegisterProfilePrefs(registry); + invalidation::InvalidatorRegistrarWithMemory::RegisterProfilePrefs(registry); ++#if BUILDFLAG(ENABLE_IPFS) ++ if (base::FeatureList::IsEnabled(ipfs::kEnableIpfs)) { ++ ipfs::RegisterPreferences(registry); ++ } ++#endif + language::LanguagePrefs::RegisterProfilePrefs(registry); + login_detection::prefs::RegisterProfilePrefs(registry); + lookalikes::RegisterProfilePrefs(registry); +diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc +index 246ec9c5c911f..5d66d133a7907 100644 +--- a/chrome/common/chrome_content_client.cc ++++ b/chrome/common/chrome_content_client.cc +@@ -296,6 +296,12 @@ void ChromeContentClient::AddAdditionalSchemes(Schemes* schemes) { + #if BUILDFLAG(IS_ANDROID) + schemes->local_schemes.push_back(url::kContentScheme); + #endif ++ for ( const char* ip_s : {"ipfs", "ipns"} ) { ++ schemes->standard_schemes.push_back(ip_s); ++ schemes->cors_enabled_schemes.push_back(ip_s); ++ schemes->secure_schemes.push_back(ip_s); ++ schemes->csp_bypassing_schemes.push_back(ip_s); ++ } + } + + std::u16string ChromeContentClient::GetLocalizedString(int message_id) { +diff --git a/components/cbor/reader.cc b/components/cbor/reader.cc +index 306ba52fa4944..6b13b3a679a65 100644 +--- a/components/cbor/reader.cc ++++ b/components/cbor/reader.cc +@@ -22,7 +22,7 @@ + namespace cbor { + + namespace constants { +-const char kUnsupportedMajorType[] = "Unsupported major type."; ++const char kUnsupportedMajorType[] = "Unsupported major type operation."; + } + + namespace { +@@ -156,7 +156,11 @@ absl::optional Reader::DecodeCompleteDataItem(const Config& config, + case Value::Type::FLOAT_VALUE: + // Floating point values also go here since they are also type 7. + return DecodeToSimpleValueOrFloat(*header, config); +- case Value::Type::TAG: // We explicitly don't support TAG. ++ case Value::Type::TAG: ++ if (config.parse_tags) { ++ return ReadTagContent(*header, config, max_nesting_level); ++ } ++ break; + case Value::Type::NONE: + case Value::Type::INVALID_UTF8: + break; +@@ -347,6 +351,17 @@ absl::optional Reader::ReadByteStringContent( + return Value(std::move(cbor_byte_string)); + } + ++absl::optional Reader::ReadTagContent( ++ const Reader::DataItemHeader& header, ++ const Config& config, ++ int max_nesting_level) { ++ auto tagged_content = DecodeCompleteDataItem(config, max_nesting_level); ++ if (tagged_content.has_value()) { ++ tagged_content.value().SetTag(header.value); ++ } ++ return tagged_content; ++} ++ + absl::optional Reader::ReadArrayContent( + const Reader::DataItemHeader& header, + const Config& config, +diff --git a/components/cbor/reader.h b/components/cbor/reader.h +index f0b43a5517528..a57e277a1bc66 100644 +--- a/components/cbor/reader.h ++++ b/components/cbor/reader.h +@@ -130,6 +130,11 @@ class CBOR_EXPORT Reader { + // during decoding will set raise the `UNSUPPORTED_FLOATING_POINT_VALUE` + // error. + bool allow_floating_point = false; ++ ++ // If the parser encounters a TAG element, should it be parsed out and ++ // the tag value saved (true), or should the entire node and its content ++ // be discarded (false) ++ bool parse_tags = false; + }; + + Reader(const Reader&) = delete; +@@ -204,6 +209,9 @@ class CBOR_EXPORT Reader { + absl::optional ReadMapContent(const DataItemHeader& header, + const Config& config, + int max_nesting_level); ++ absl::optional ReadTagContent(const DataItemHeader& header, ++ const Config& config, ++ int max_nesting_level); + absl::optional ReadByte(); + absl::optional> ReadBytes(uint64_t num_bytes); + bool IsKeyInOrder(const Value& new_key, +diff --git a/components/cbor/reader_unittest.cc b/components/cbor/reader_unittest.cc +index 83d44a48d6dfa..a6ec5299b3241 100644 +--- a/components/cbor/reader_unittest.cc ++++ b/components/cbor/reader_unittest.cc +@@ -1451,5 +1451,42 @@ TEST(CBORReaderTest, AllowInvalidUTF8) { + EXPECT_FALSE(cbor); + EXPECT_EQ(Reader::DecoderError::INVALID_UTF8, error); + } ++TEST(CBORReaderTest, RejectsTagUnderDefaultConfig) { ++ static const uint8_t kTaggedCbor[] = { ++ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x71, 0x12, 0x20, 0x69, 0xea, 0x07, ++ 0x40, 0xf9, 0x80, 0x7a, 0x28, 0xf4, 0xd9, 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, 0x07, 0x2c, 0x90, 0x26, 0x6a, 0xb3, 0xe7, ++ 0x9d, 0xf6, 0x3a, 0x36, 0x5b ++ }; ++ Reader::Config config; ++ absl::optional cbor = Reader::Read(kTaggedCbor, config); ++ EXPECT_FALSE(cbor.has_value()); ++} ++TEST(CBORReaderTest, ReadsTagWhenConfiguredToDoSo) { ++ static const uint8_t kTaggedCbor[] = { ++ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x71, 0x12, 0x20, 0x69, 0xea, 0x07, ++ 0x40, 0xf9, 0x80, 0x7a, 0x28, 0xf4, 0xd9, 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, 0x07, 0x2c, 0x90, 0x26, 0x6a, 0xb3, 0xe7, ++ 0x9d, 0xf6, 0x3a, 0x36, 0x5b ++ }; ++ Reader::Config config; ++ config.parse_tags = true; ++ absl::optional cbor = Reader::Read(kTaggedCbor, config); ++ EXPECT_TRUE(cbor.has_value()); ++ auto& v = cbor.value(); ++ EXPECT_TRUE(v.has_tag()); ++ EXPECT_EQ(v.GetTag(),42UL); ++ EXPECT_TRUE(v.is_bytestring()); ++ EXPECT_EQ(v.type(), Value::Type::BYTE_STRING); ++ auto& bytes = v.GetBytestring(); ++ EXPECT_EQ(bytes.size(), 37UL); ++ EXPECT_EQ(bytes.at(0), 0x00);//identity multibase (e.g. not base-encoded, bytes are themselves) ++ EXPECT_EQ(bytes.at(1), 0x01);//CID version 1 ++ EXPECT_EQ(bytes.at(2), 0x71);//codec = dag-cbor ++ EXPECT_EQ(bytes.at(3), 0x12);//multihash = 18 = sha2-256 ++ EXPECT_EQ(bytes.at(4), 0x20);//hash length = 32 bytes ++ EXPECT_EQ(bytes.at(5), 0x69);//first byte of hash digest ++ EXPECT_EQ(bytes.at(36),0x5b);//last byte of hash digest ++} + + } // namespace cbor +diff --git a/components/cbor/values.cc b/components/cbor/values.cc +index 02498209c820e..34055aef24cfe 100644 +--- a/components/cbor/values.cc ++++ b/components/cbor/values.cc +@@ -66,32 +66,34 @@ Value::Value(Type type) : type_(type) { + NOTREACHED(); + } + +-Value::Value(SimpleValue in_simple) +- : type_(Type::SIMPLE_VALUE), simple_value_(in_simple) { ++Value::Value(SimpleValue in_simple, uint64_t tag) ++ : type_(Type::SIMPLE_VALUE), simple_value_(in_simple), tag_(tag) { + CHECK(static_cast(in_simple) >= 20 && static_cast(in_simple) <= 23); + } + +-Value::Value(bool boolean_value) : type_(Type::SIMPLE_VALUE) { ++Value::Value(bool boolean_value, uint64_t tag) : type_(Type::SIMPLE_VALUE), tag_(tag) { + simple_value_ = boolean_value ? Value::SimpleValue::TRUE_VALUE + : Value::SimpleValue::FALSE_VALUE; + } + +-Value::Value(double float_value) +- : type_(Type::FLOAT_VALUE), float_value_(float_value) {} ++Value::Value(double float_value, uint64_t tag) ++ : type_(Type::FLOAT_VALUE), float_value_(float_value), tag_(tag) {} + +-Value::Value(int integer_value) +- : Value(base::checked_cast(integer_value)) {} ++Value::Value(int integer_value, uint64_t tag) ++ : Value(base::checked_cast(integer_value), tag) {} + +-Value::Value(int64_t integer_value) : integer_value_(integer_value) { ++Value::Value(int64_t integer_value, uint64_t tag) : integer_value_(integer_value), tag_(tag) { + type_ = integer_value >= 0 ? Type::UNSIGNED : Type::NEGATIVE; + } + +-Value::Value(base::span in_bytes) ++Value::Value(base::span in_bytes, uint64_t tag) + : type_(Type::BYTE_STRING), +- bytestring_value_(in_bytes.begin(), in_bytes.end()) {} ++ bytestring_value_(in_bytes.begin(), in_bytes.end()), ++ tag_(tag) ++ {} + +-Value::Value(base::span in_bytes, Type type) +- : type_(type), bytestring_value_(in_bytes.begin(), in_bytes.end()) { ++Value::Value(base::span in_bytes, Type type, uint64_t tag) ++ : type_(type), bytestring_value_(in_bytes.begin(), in_bytes.end()), tag_(tag) { + DCHECK(type_ == Type::BYTE_STRING || type_ == Type::INVALID_UTF8); + } + +@@ -117,7 +119,8 @@ Value::Value(std::string&& in_string, Type type) noexcept : type_(type) { + } + } + +-Value::Value(base::StringPiece in_string, Type type) : type_(type) { ++Value::Value(base::StringPiece in_string, Type type, uint64_t tag) ++: type_(type), tag_(tag) { + switch (type_) { + case Type::STRING: + new (&string_value_) std::string(); +@@ -133,16 +136,18 @@ Value::Value(base::StringPiece in_string, Type type) : type_(type) { + } + } + +-Value::Value(const ArrayValue& in_array) : type_(Type::ARRAY), array_value_() { ++Value::Value(const ArrayValue& in_array, uint64_t tag) ++: type_(Type::ARRAY), array_value_(), tag_(tag) { + array_value_.reserve(in_array.size()); + for (const auto& val : in_array) + array_value_.emplace_back(val.Clone()); + } + +-Value::Value(ArrayValue&& in_array) noexcept +- : type_(Type::ARRAY), array_value_(std::move(in_array)) {} ++Value::Value(ArrayValue&& in_array, uint64_t tag) noexcept ++ : type_(Type::ARRAY), array_value_(std::move(in_array)), tag_(tag) {} + +-Value::Value(const MapValue& in_map) : type_(Type::MAP), map_value_() { ++Value::Value(const MapValue& in_map, uint64_t tag) ++: type_(Type::MAP), map_value_(), tag_(tag) { + map_value_.reserve(in_map.size()); + for (const auto& it : in_map) + map_value_.emplace_hint(map_value_.end(), it.first.Clone(), +@@ -168,31 +173,36 @@ Value Value::Clone() const { + case Type::NONE: + return Value(); + case Type::INVALID_UTF8: +- return Value(bytestring_value_, Type::INVALID_UTF8); ++ return Value(bytestring_value_, Type::INVALID_UTF8, tag_); + case Type::UNSIGNED: + case Type::NEGATIVE: +- return Value(integer_value_); ++ return Value(integer_value_, tag_); + case Type::BYTE_STRING: +- return Value(bytestring_value_); ++ return Value(bytestring_value_, tag_); + case Type::STRING: +- return Value(string_value_); ++ return Value(string_value_, Type::STRING, tag_); + case Type::ARRAY: +- return Value(array_value_); ++ return Value(array_value_, tag_); + case Type::MAP: +- return Value(map_value_); ++ return Value(map_value_, tag_); + case Type::TAG: + NOTREACHED() << constants::kUnsupportedMajorType; + return Value(); + case Type::SIMPLE_VALUE: +- return Value(simple_value_); ++ return Value(simple_value_, tag_); + case Type::FLOAT_VALUE: +- return Value(float_value_); ++ return Value(float_value_, tag_); + } + + NOTREACHED(); + return Value(); + } + ++Value& Value::SetTag(uint64_t tag) noexcept { ++ tag_ = tag; ++ return *this; ++} ++ + Value::SimpleValue Value::GetSimpleValue() const { + CHECK(is_simple()); + return simple_value_; +@@ -258,9 +268,14 @@ const Value::BinaryValue& Value::GetInvalidUTF8() const { + return bytestring_value_; + } + ++uint64_t Value::GetTag() const { ++ CHECK(has_tag()); ++ return tag_; ++} ++ + void Value::InternalMoveConstructFrom(Value&& that) { + type_ = that.type_; +- ++ tag_ = that.tag_; + switch (type_) { + case Type::UNSIGNED: + case Type::NEGATIVE: +diff --git a/components/cbor/values.h b/components/cbor/values.h +index d81ef5607c55a..10216a8dcdc57 100644 +--- a/components/cbor/values.h ++++ b/components/cbor/values.h +@@ -127,28 +127,29 @@ class CBOR_EXPORT Value { + + explicit Value(Type type); + +- explicit Value(SimpleValue in_simple); +- explicit Value(bool boolean_value); +- explicit Value(double in_float); ++ explicit Value(SimpleValue in_simple, uint64_t tag = NO_TAG); ++ explicit Value(bool boolean_value, uint64_t tag = NO_TAG); ++ explicit Value(double in_float, uint64_t tag = NO_TAG); + +- explicit Value(int integer_value); +- explicit Value(int64_t integer_value); ++ explicit Value(int integer_value, uint64_t tag = NO_TAG); ++ explicit Value(int64_t integer_value, uint64_t tag = NO_TAG); + explicit Value(uint64_t integer_value) = delete; + +- explicit Value(base::span in_bytes); ++ explicit Value(base::span in_bytes, uint64_t tag = NO_TAG); + explicit Value(BinaryValue&& in_bytes) noexcept; + + explicit Value(const char* in_string, Type type = Type::STRING); + explicit Value(std::string&& in_string, Type type = Type::STRING) noexcept; +- explicit Value(base::StringPiece in_string, Type type = Type::STRING); ++ explicit Value(base::StringPiece in_string, Type type = Type::STRING, uint64_t tag = NO_TAG); + +- explicit Value(const ArrayValue& in_array); +- explicit Value(ArrayValue&& in_array) noexcept; ++ explicit Value(const ArrayValue& in_array, uint64_t tag = NO_TAG); ++ explicit Value(ArrayValue&& in_array, uint64_t tag = NO_TAG) noexcept; + +- explicit Value(const MapValue& in_map); ++ explicit Value(const MapValue& in_map, uint64_t tag = NO_TAG); + explicit Value(MapValue&& in_map) noexcept; + + Value& operator=(Value&& that) noexcept; ++ Value& SetTag(uint64_t) noexcept; + + Value(const Value&) = delete; + Value& operator=(const Value&) = delete; +@@ -179,6 +180,7 @@ class CBOR_EXPORT Value { + bool is_string() const { return type() == Type::STRING; } + bool is_array() const { return type() == Type::ARRAY; } + bool is_map() const { return type() == Type::MAP; } ++ bool has_tag() const { return tag_ != NO_TAG; } + + // These will all fatally assert if the type doesn't match. + SimpleValue GetSimpleValue() const; +@@ -194,12 +196,13 @@ class CBOR_EXPORT Value { + const ArrayValue& GetArray() const; + const MapValue& GetMap() const; + const BinaryValue& GetInvalidUTF8() const; ++ uint64_t GetTag() const; + + private: + friend class Reader; + // This constructor allows INVALID_UTF8 values to be created, which only + // |Reader| and InvalidUTF8StringValueForTesting() may do. +- Value(base::span in_bytes, Type type); ++ Value(base::span in_bytes, Type type, uint64_t tag = NO_TAG); + + Type type_; + +@@ -213,6 +216,11 @@ class CBOR_EXPORT Value { + MapValue map_value_; + }; + ++ //This value specified as Invalid, ++ // used here to represent absence of TAG ++ constexpr static uint64_t NO_TAG = 0xFFFF; ++ uint64_t tag_ = NO_TAG; ++ + void InternalMoveConstructFrom(Value&& that); + void InternalCleanup(); + }; +diff --git a/components/cbor/writer.cc b/components/cbor/writer.cc +index bb22754d36a07..aae4027836377 100644 +--- a/components/cbor/writer.cc ++++ b/components/cbor/writer.cc +@@ -47,6 +47,9 @@ bool Writer::EncodeCBOR(const Value& node, + if (max_nesting_level < 0) + return false; + ++ if (node.has_tag()) { ++ StartItem(Value::Type::TAG, node.GetTag()); ++ } + switch (node.type()) { + case Value::Type::NONE: { + StartItem(Value::Type::BYTE_STRING, 0); +diff --git a/components/cbor/writer_unittest.cc b/components/cbor/writer_unittest.cc +index e3bffe20734bc..0ed569ae164a0 100644 +--- a/components/cbor/writer_unittest.cc ++++ b/components/cbor/writer_unittest.cc +@@ -522,4 +522,31 @@ TEST(CBORWriterTest, OverlyNestedCBOR) { + EXPECT_FALSE(Writer::Write(Value(map), 4).has_value()); + } + ++TEST(CBORWriterTest, CanWriteTag) { ++ std::array content{ ++ 0x00, 0x01, 0x71, 0x12, 0x20, ++ 0x69, 0xea, 0x07, 0x40, 0xf9, ++ 0x80, 0x7a, 0x28, 0xf4, 0xd9, ++ 0x32, 0xc6, 0x2e, 0x7c, 0x1c, ++ 0x83, 0xbe, 0x05, 0x5e, 0x55, ++ 0x07, 0x2c, 0x90, 0x26, 0x6a, ++ 0xb3, 0xe7, 0x9d, 0xf6, 0x3a, ++ 0x36, 0x5b ++ }; ++ Value to_write(content); ++ to_write.SetTag(42); ++ auto result = Writer::Write(to_write); ++ EXPECT_TRUE(result.has_value()); ++ auto& bytes = result.value(); ++ EXPECT_EQ(bytes.size(), 41UL); ++ EXPECT_EQ(bytes.at(0), 0xd8); ++ EXPECT_EQ(bytes.at(1), 0x2a); ++ EXPECT_EQ(bytes.at(2), 0x58); ++ EXPECT_EQ(bytes.at(3), 0x25); ++ for (auto i = 0UL; i < content.size(); ++i) { ++ ASSERT_LT(i + 4UL, bytes.size()); ++ ASSERT_EQ(content.at(i), bytes.at(i+4UL)); ++ } ++} ++ + } // namespace cbor +diff --git a/components/open_from_clipboard/clipboard_recent_content_generic.cc b/components/open_from_clipboard/clipboard_recent_content_generic.cc +index 4dcafecbc66c6..d205209c08162 100644 +--- a/components/open_from_clipboard/clipboard_recent_content_generic.cc ++++ b/components/open_from_clipboard/clipboard_recent_content_generic.cc +@@ -20,7 +20,7 @@ + namespace { + // Schemes appropriate for suggestion by ClipboardRecentContent. + const char* kAuthorizedSchemes[] = { +- url::kAboutScheme, url::kDataScheme, url::kHttpScheme, url::kHttpsScheme, ++ url::kAboutScheme, url::kDataScheme, url::kHttpScheme, url::kHttpsScheme, "ipfs", "ipns" + // TODO(mpearson): add support for chrome:// URLs. Right now the scheme + // for that lives in content and is accessible via + // GetEmbedderRepresentationOfAboutScheme() or content::kChromeUIScheme +diff --git a/net/dns/dns_config_service_linux.cc b/net/dns/dns_config_service_linux.cc +index 5273da5190277..12b28b86a4c00 100644 +--- a/net/dns/dns_config_service_linux.cc ++++ b/net/dns/dns_config_service_linux.cc +@@ -272,11 +272,11 @@ bool IsNsswitchConfigCompatible( + // Ignore any entries after `kDns` because Chrome will fallback to the + // system resolver if a result was not found in DNS. + return true; +- ++ case NsswitchReader::Service::kResolve: ++ break; + case NsswitchReader::Service::kMdns: + case NsswitchReader::Service::kMdns4: + case NsswitchReader::Service::kMdns6: +- case NsswitchReader::Service::kResolve: + case NsswitchReader::Service::kNis: + RecordIncompatibleNsswitchReason( + IncompatibleNsswitchReason::kIncompatibleService, +diff --git a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc +index 4eadf46ea0c24..d62fc7fb14e01 100644 +--- a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc ++++ b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc +@@ -67,7 +67,7 @@ class URLSchemesRegistry final { + // is considered secure. Additional checks are performed to ensure that + // other http pages are filtered out. + service_worker_schemes({"http", "https"}), +- fetch_api_schemes({"http", "https"}), ++ fetch_api_schemes({"http", "https", "ipfs", "ipns"}), + allowed_in_referrer_schemes({"http", "https"}) { + for (auto& scheme : url::GetCorsEnabledSchemes()) + cors_enabled_schemes.insert(scheme.c_str()); +diff --git a/url/BUILD.gn b/url/BUILD.gn +index 0ac17c08dc5bc..2497d02658bb3 100644 +--- a/url/BUILD.gn ++++ b/url/BUILD.gn +@@ -5,6 +5,7 @@ + import("//build/buildflag_header.gni") + import("//testing/libfuzzer/fuzzer_test.gni") + import("//testing/test.gni") ++import("//third_party/ipfs_client/args.gni") + import("features.gni") + + import("//build/config/cronet/config.gni") +@@ -68,6 +69,7 @@ component("url") { + public_deps = [ + "//base", + "//build:robolectric_buildflags", ++ "//third_party/ipfs_client:ipfs_buildflags", + ] + + configs += [ "//build/config/compiler:wexit_time_destructors" ] +@@ -90,6 +92,11 @@ component("url") { + public_configs = [ "//third_party/jdk" ] + } + ++ if (enable_ipfs) { ++ sources += [ "url_canon_ipfs.cc" ] ++ deps += [ "//third_party/ipfs_client:ipfs_client" ] ++ } ++ + if (is_win) { + # Don't conflict with Windows' "url.dll". + output_name = "url_lib" +diff --git a/url/url_canon.h b/url/url_canon.h +index 8c48f9825d8cf..b9ad961e1b123 100644 +--- a/url/url_canon.h ++++ b/url/url_canon.h +@@ -804,6 +804,23 @@ bool CanonicalizeMailtoURL(const char16_t* spec, + CanonOutput* output, + Parsed* new_parsed); + ++COMPONENT_EXPORT(URL) ++bool CanonicalizeIpfsURL(const char* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* query_converter, ++ CanonOutput* output, ++ Parsed* new_parsed); ++COMPONENT_EXPORT(URL) ++bool CanonicalizeIpfsURL(const char16_t* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* query_converter, ++ CanonOutput* output, ++ Parsed* new_parsed); ++ + // Part replacer -------------------------------------------------------------- + + // Internal structure used for storing separate strings for each component. +diff --git a/url/url_canon_ipfs.cc b/url/url_canon_ipfs.cc +new file mode 100644 +index 0000000000000..d7c9fdc78eb91 +--- /dev/null ++++ b/url/url_canon_ipfs.cc +@@ -0,0 +1,55 @@ ++#include "url_canon_internal.h" ++ ++#include ++#include ++ ++#include ++ ++bool url::CanonicalizeIpfsURL(const char* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* charset_converter, ++ CanonOutput* output, ++ Parsed* output_parsed) { ++ if ( spec_len < 1 || !spec ) { ++ return false; ++ } ++ if ( parsed.host.len < 1 ) { ++ return false; ++ } ++ std::string_view cid_str{ spec + parsed.host.begin, static_cast(parsed.host.len) }; ++ auto cid = ipfs::Cid(cid_str); ++ if ( !cid.valid() ) { ++ cid = ipfs::id_cid::forText( std::string{cid_str} + " is not a valid CID." ); ++ } ++ auto as_str = cid.to_string(); ++ if ( as_str.empty() ) { ++ return false; ++ } ++ std::string stdurl{ spec, static_cast(parsed.host.begin) }; ++ stdurl.append( as_str ); ++ stdurl.append( spec + parsed.host.end(), spec_len - parsed.host.end() ); ++ spec = stdurl.data(); ++ spec_len = static_cast(stdurl.size()); ++ Parsed parsed_input; ++ ParseStandardURL(spec, spec_len, &parsed_input); ++ return CanonicalizeStandardURL( ++ spec, ++ parsed_input, ++ scheme_type, ++ charset_converter, ++ output, output_parsed ++ ); ++} ++bool url::CanonicalizeIpfsURL(const char16_t* spec, ++ int spec_len, ++ const Parsed& parsed, ++ SchemeType scheme_type, ++ CharsetConverter* query_converter, ++ CanonOutput* output, ++ Parsed* new_parsed) { ++ RawCanonOutput<2048> as8; ++ ConvertUTF16ToUTF8(spec, spec_len, &as8); ++ return CanonicalizeIpfsURL(as8.data(), as8.length(), parsed, scheme_type, query_converter, output, new_parsed); ++} +diff --git a/url/url_util.cc b/url/url_util.cc +index 6f83f33c01c6b..a248e11c49445 100644 +--- a/url/url_util.cc ++++ b/url/url_util.cc +@@ -273,8 +273,15 @@ bool DoCanonicalize(const CHAR* spec, + } else if (DoCompareSchemeComponent(spec, scheme, url::kFileSystemScheme)) { + // Filesystem URLs are special. + ParseFileSystemURL(spec, spec_len, &parsed_input); +- success = CanonicalizeFileSystemURL(spec, parsed_input, charset_converter, +- output, output_parsed); ++ success = CanonicalizeFileSystemURL(spec, parsed_input, ++ charset_converter, output, ++ output_parsed); ++ ++ } else if (DoCompareSchemeComponent(spec, scheme, "ipfs")) { ++ // Switch multibase away from case-sensitive ones before continuing canonicalization. ++ ParseStandardURL(spec, spec_len, &parsed_input); ++ success = CanonicalizeIpfsURL(spec, spec_len, parsed_input, scheme_type, ++ charset_converter, output, output_parsed); + + } else if (DoIsStandard(spec, scheme, &scheme_type)) { + // All "normal" URLs. + diff --git a/library/include/libp2p/multi/multibase_codec.hpp b/library/include/libp2p/multi/multibase_codec.hpp deleted file mode 100644 index c7b9cbd1..00000000 --- a/library/include/libp2p/multi/multibase_codec.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef LIBP2P_MULTIBASE_HPP -#define LIBP2P_MULTIBASE_HPP - -#include "vocab/expected.h" - -#include -#include -#include - -#include - -namespace libp2p::multi { -/** - * Allows to distinguish between different base-encoded binaries - * See more: https://github.com/multiformats/multibase - */ -class MultibaseCodec { - public: - enum class Error { UNSUPPORTED_BASE = 1, INPUT_TOO_SHORT, BASE_CODEC_ERROR }; - - using ByteBuffer = common::ByteArray; - using FactoryResult = ipfs::expected; - - virtual ~MultibaseCodec() = default; - /** - * Encodings, supported by this Multibase - * @sa https://github.com/multiformats/multibase#multibase-table - */ - enum class Encoding : char { - BASE16_LOWER = 'f', - BASE16_UPPER = 'F', - BASE32_LOWER = 'b', - BASE32_UPPER = 'B', - BASE36 = 'k', - BASE58 = 'z', - BASE64 = 'm' - }; - - /** - * Encode the incoming bytes - * @param bytes to be encoded - * @param encoding - base of the desired encoding - * @return encoded string WITH an encoding prefix - */ - virtual std::string encode(const ByteBuffer& bytes, - Encoding encoding) const = 0; - - /** - * Decode the incoming string - * @param string to be decoded - * @return bytes, if decoding was successful, error otherwise - */ - virtual FactoryResult decode(std::string_view string) const = 0; -}; - -bool case_critical(MultibaseCodec::Encoding); - -} // namespace libp2p::multi - -#endif // LIBP2P_MULTIBASE_HPP diff --git a/library/src/ipfs_client/car.cc b/library/src/ipfs_client/car.cc index 6d550030..b231e8d0 100644 --- a/library/src/ipfs_client/car.cc +++ b/library/src/ipfs_client/car.cc @@ -59,7 +59,6 @@ auto Self::NextBlock() -> std::optional { rv.bytes = data_.subspan(0U, len->toUInt64()); data_ = data_.subspan(len->toUInt64()); if (rv.cid.ReadStart(rv.bytes)) { - // TODO : check hash return rv; } return std::nullopt; diff --git a/library/src/ipfs_client/gateways.cc b/library/src/ipfs_client/gateways.cc index 75472078..68eaa7c3 100644 --- a/library/src/ipfs_client/gateways.cc +++ b/library/src/ipfs_client/gateways.cc @@ -100,19 +100,19 @@ auto ipfs::Gateways::DefaultGateways() -> GatewayList { } return result; } - return {{"http://localhost:8080/"s, 892}, - {"https://jcsl.hopto.org/"s, 837}, - {"https://human.mypinata.cloud/"s, 748}, - {"https://ipfs.io/"s, 732}, - {"https://gateway.ipfs.io/"s, 630}, - {"https://dweb.link/"s, 525}, - {"https://gateway.pinata.cloud/"s, 467}, - {"https://ipfs.joaoleitao.org/"s, 364}, - {"https://ipfs.runfission.com/"s, 346}, - {"https://nftstorage.link/"s, 245}, - {"https://w3s.link/"s, 174}, - {"https://ipfs.fleek.co/"s, 143}, - {"https://permaweb.eu.org/"s, 99}, + return {{"http://localhost:8080/"s, 885}, + {"https://jcsl.hopto.org/"s, 833}, + {"https://human.mypinata.cloud/"s, 737}, + {"https://ipfs.io/"s, 731}, + {"https://gateway.ipfs.io/"s, 628}, + {"https://dweb.link/"s, 512}, + {"https://gateway.pinata.cloud/"s, 455}, + {"https://ipfs.joaoleitao.org/"s, 355}, + {"https://ipfs.runfission.com/"s, 341}, + {"https://nftstorage.link/"s, 239}, + {"https://w3s.link/"s, 166}, + {"https://ipfs.fleek.co/"s, 133}, + {"https://permaweb.eu.org/"s, 96}, {"https://hardbin.com/"s, 4}, {"https://jorropo.net/"s, 3}, {"https://ipfs.jpu.jp/"s, 2}, diff --git a/library/src/ipfs_client/gw/multi_gateway_requestor.cc b/library/src/ipfs_client/gw/multi_gateway_requestor.cc index 974985b4..97af40d6 100644 --- a/library/src/ipfs_client/gw/multi_gateway_requestor.cc +++ b/library/src/ipfs_client/gw/multi_gateway_requestor.cc @@ -6,7 +6,6 @@ #include #include -#include using Self = ipfs::gw::MultiGatewayRequestor; @@ -39,8 +38,8 @@ bool Self::Process(RequestPtr const& req) { auto bored = 0U; while (auto gw = api_->GetGateway(config_idx++)) { if (state_iter == state_.end() || state_iter->first > gw->prefix) { - LOG(INFO) << "A new gateway has entered the chat: " << gw->prefix << '=' - << gw->rate; + VLOG(1) << "A new gateway has entered the chat: " << gw->prefix << '=' + << gw->rate; // One can insert like this because state_ is std::map w/ stable iterators state_iter = state_.insert({gw->prefix, GatewayState{}}).first; candidates.emplace_back(LONG_MAX, gw->prefix, &(state_iter->second)); @@ -76,8 +75,8 @@ bool Self::Process(RequestPtr const& req) { return false; } auto to_send = std::max(bored / 2, 3U); - namespace vw = std::ranges::views; - for (auto& [score, prefix, state] : candidates | vw::reverse) { + std::sort(candidates.begin(), candidates.end(), std::greater{}); + for (auto& [score, prefix, state] : candidates) { DoSend(req, prefix, *state); if (!--to_send) { return true; diff --git a/library/src/ipfs_client/orchestrator.cc b/library/src/ipfs_client/orchestrator.cc index e9de18d6..b66cfb15 100644 --- a/library/src/ipfs_client/orchestrator.cc +++ b/library/src/ipfs_client/orchestrator.cc @@ -73,8 +73,8 @@ void Self::from_tree(std::shared_ptr req, hit_path.push_back('/'); } hit_path.append(response->location_); - LOG(INFO) << "Request for " << req->path() << " returned a location of " - << response->location_ << " and a body of " + VLOG(1) << "Request for " << req->path() << " returned a location of " + << response->location_ << " and a body of " << response->body_.size() << " bytes, sniffing mime from " << hit_path; response->mime_ = sniff(SlashDelimited{hit_path}, response->body_); @@ -141,8 +141,8 @@ std::string Self::sniff(ipfs::SlashDelimited p, std::string const& body) const { ext.assign(file_name, dot + 1); } auto result = api_->MimeType(ext, body, fake_url); - LOG(INFO) << "Deduced mime from (ext=" << ext << " body of " << body.size() - << " bytes, 'url'=" << fake_url << ")=" << result; + VLOG(1) << "Deduced mime from (ext=" << ext << " body of " << body.size() + << " bytes, 'url'=" << fake_url << ")=" << result; return result; } diff --git a/library/src/ipfs_client/pb_dag.cc b/library/src/ipfs_client/pb_dag.cc index 6f72bcf2..86cbb42d 100644 --- a/library/src/ipfs_client/pb_dag.cc +++ b/library/src/ipfs_client/pb_dag.cc @@ -139,7 +139,6 @@ std::string ipfs::PbDag::LinkCid(ipfs::ByteView binary_link_hash) const { bool ipfs::PbDag::cid_matches_data(ContextApi& api) const { if (!cid_) { - // TODO - probably remove those constructors and make cid_ not optional return true; } if (type() == Type::Invalid) { diff --git a/library/src/ipfs_client/pb_dag_unittest.cc b/library/src/ipfs_client/pb_dag_unittest.cc index 37e7090b..418e4c0f 100644 --- a/library/src/ipfs_client/pb_dag_unittest.cc +++ b/library/src/ipfs_client/pb_dag_unittest.cc @@ -41,7 +41,7 @@ TEST(BlockTest, IdentityBlockValidates) { EXPECT_TRUE(block.valid()); EXPECT_TRUE(block.is_file()); MockApi api; - // TODO: if this fails, awesome. Change the block_bytes to "Ipsum lorem" + // if this fails, awesome. Change the block_bytes to "Ipsum lorem" EXPECT_TRUE(block.cid_matches_data(api)); } TEST(BlockTest, DirectoryCopiedIsStillDirectory) { diff --git a/library/src/ipfs_client/test_context.cc b/library/src/ipfs_client/test_context.cc index 3fe9675e..56c885ea 100644 --- a/library/src/ipfs_client/test_context.cc +++ b/library/src/ipfs_client/test_context.cc @@ -122,7 +122,7 @@ class HttpSession : public std::enable_shared_from_this { int expiry_seconds_ = 91; std::string host_, port_, target_; ipfs::HttpRequestDescription desc_; - tcp::resolver::results_type resolution_; + static std::map resolutions_; std::string parsed_host_; boost::beast::http::response_parser response_parser_; @@ -174,7 +174,9 @@ class HttpSession : public std::enable_shared_from_this { response_parser_.body_limit(boost::none); } } - + tcp::resolver::results_type& resolution() { + return resolutions_[host_ + port_]; + } // Start the asynchronous operation void run() { auto parsed_host_ = parse_url(); @@ -197,21 +199,24 @@ class HttpSession : public std::enable_shared_from_this { // std::clog << "Setting Accept: " << desc_.accept << '\n'; req_.set("Accept", desc_.accept); } - extend_time(); - GOOGLE_LOG(DEBUG) << "Starting " << desc_.url - << " with a host resolution of " << host_ << ':' << port_; - // Look up the domain name - resolver_.async_resolve(host_, port_, - boost::beast::bind_front_handler( - &HttpSession::on_resolve, shared_from_this())); + if (resolution().empty()) { + GOOGLE_LOG(DEBUG) << "Starting " << desc_.url + << " with a host resolution of " << host_ << ':' + << port_; + extend_time(); + resolver_.async_resolve( + host_, port_, + boost::beast::bind_front_handler(&HttpSession::on_resolve, + shared_from_this())); + } else { + on_resolve({}, resolution()); + } } - void on_resolve(boost::beast::error_code ec, tcp::resolver::results_type results) { if (ec) return fail(ec, "resolve"); - resolution_ = results; - extend_time(); + resolution() = results; for (auto& ep : results) { GOOGLE_LOG(DEBUG) << desc_.url << " Resolved " << host_ << ", now connecting to " @@ -308,11 +313,12 @@ class HttpSession : public std::enable_shared_from_this { auto loc = (*res_)[boost::beast::http::field::location]; if (loc.size()) { desc_.url = loc; + close(); GOOGLE_LOG(WARNING) << "Redirecting to " << loc << " aka " << desc_.url; res_ = boost::beast::http::response{}; req_.set(boost::beast::http::field::host, parse_url()); req_.target(target_); - on_resolve({}, resolution_); + on_resolve({}, resolution()); return; } } @@ -325,26 +331,32 @@ class HttpSession : public std::enable_shared_from_this { << " response incorrect content type: " << content_type << " != " << desc_.accept; } + close(); + } + void close() { if (use_ssl()) { stream_.async_shutdown(boost::beast::bind_front_handler( &HttpSession::on_shutdown, shared_from_this())); } else { boost::beast::get_lowest_layer(stream_).close(); - if (ec && ec != boost::beast::errc::not_connected) - return fail(ec, "shutdown"); } } void on_shutdown(boost::beast::error_code ec) { - if (ec == boost::asio::error::eof) { - ec = {}; + namespace E = boost::asio::error; + switch (ec.value()) { + case 0: + case 2: + case ENOTCONN: + return; + default: + return fail(ec, "shutdown"); } - if (ec) - return fail(ec, "shutdown"); - - // If we get here then the connection is closed gracefully } }; +std::map + HttpSession::resolutions_; + void Self::SendHttpRequest(HttpRequestDescription desc, HttpCompleteCallback cb) const { auto sess = std::make_shared(io_, ssl_ctx_, desc, cb); diff --git a/library/src/libp2p/crypto/protobuf_key.hpp b/library/src/libp2p/crypto/protobuf_key.hpp deleted file mode 100644 index 459426f8..00000000 --- a/library/src/libp2p/crypto/protobuf_key.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright Soramitsu Co., Ltd. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef KAGOME_PROTOBUF_KEY_HPP -#define KAGOME_PROTOBUF_KEY_HPP - -#include -#include - -#include - -namespace libp2p::crypto { - /** - * Strict type for key, which is encoded into Protobuf format - */ - struct ProtobufKey : public boost::equality_comparable { - explicit ProtobufKey(std::vector key) : key{std::move(key)} {} - - std::vector key; - - bool operator==(const ProtobufKey &other) const { - return key == other.key; - } - }; -} // namespace libp2p::crypto - -#endif // KAGOME_PROTOBUF_KEY_HPP diff --git a/test_data/blocks/QmQj5ARTnu85pJ26Mxmhhiddvkkg7cQDZc6wszYMWetkcL b/test_data/blocks/QmQj5ARTnu85pJ26Mxmhhiddvkkg7cQDZc6wszYMWetkcL deleted file mode 100644 index 80ea606a..00000000 --- a/test_data/blocks/QmQj5ARTnu85pJ26Mxmhhiddvkkg7cQDZc6wszYMWetkcL +++ /dev/null @@ -1,2 +0,0 @@ - -Wa4 Wa5 Wa6 Wa7 Wa8 Wa9 Wb0 Wb1 Wb2 Wb3 Wb4 Wb5 Wb6 Wb7 Wb8 Wb9 Wc0 Wc1 Wc2 Wc3 Wc4 Wc5 Wc6 Wc7 Wc8 Wc9 Wd0 Wd1 Wd2 Wd3 Wd4 Wd5 Wd6 Wd7 Wd8 Wd9  \ No newline at end of file diff --git a/test_data/blocks/QmQx24y7nKXUYFX2NLWUUTw5oK2zCAgwNjyq6nSUzin76J b/test_data/blocks/QmQx24y7nKXUYFX2NLWUUTw5oK2zCAgwNjyq6nSUzin76J deleted file mode 100644 index 71f84a78..00000000 --- a/test_data/blocks/QmQx24y7nKXUYFX2NLWUUTw5oK2zCAgwNjyq6nSUzin76J +++ /dev/null @@ -1,2 +0,0 @@ - -Lc0 Lc1 Lc2 Lc3 Lc4 Lc5 Lc6 Lc7 Lc8 Lc9 Ld0 Ld1 Ld2 Ld3 Ld4 Ld5 Ld6 Ld7 Ld8 Ld9 Le0 Le1 Le2 Le3 Le4 Le5 Le6 Le7 Le8 Le9 Lf0 Lf1 Lf2 Lf3 Lf4 Lf5  \ No newline at end of file diff --git a/test_data/blocks/QmR1u7SZtyYU22pANU4WivHyqWShVMPeigJd7aeEgffEvV b/test_data/blocks/QmR1u7SZtyYU22pANU4WivHyqWShVMPeigJd7aeEgffEvV deleted file mode 100644 index ef39ec4f..00000000 --- a/test_data/blocks/QmR1u7SZtyYU22pANU4WivHyqWShVMPeigJd7aeEgffEvV +++ /dev/null @@ -1,2 +0,0 @@ - -Vp6 Vp7 Vp8 Vp9 Vq0 Vq1 Vq2 Vq3 Vq4 Vq5 Vq6 Vq7 Vq8 Vq9 Vr0 Vr1 Vr2 Vr3 Vr4 Vr5 Vr6 Vr7 Vr8 Vr9 Vs0 Vs1 Vs2 Vs3 Vs4 Vs5 Vs6 Vs7 Vs8 Vs9 Vt0 Vt1  \ No newline at end of file diff --git a/test_data/blocks/QmR3gXz9KWc3gioJECyKmC5y89a1AN27ZPzC8MSa9HGb8h b/test_data/blocks/QmR3gXz9KWc3gioJECyKmC5y89a1AN27ZPzC8MSa9HGb8h deleted file mode 100644 index e6726734..00000000 --- a/test_data/blocks/QmR3gXz9KWc3gioJECyKmC5y89a1AN27ZPzC8MSa9HGb8h +++ /dev/null @@ -1,2 +0,0 @@ - -Uj2 Uj3 Uj4 Uj5 Uj6 Uj7 Uj8 Uj9 Uk0 Uk1 Uk2 Uk3 Uk4 Uk5 Uk6 Uk7 Uk8 Uk9 Ul0 Ul1 Ul2 Ul3 Ul4 Ul5 Ul6 Ul7 Ul8 Ul9 Um0 Um1 Um2 Um3 Um4 Um5 Um6 Um7  \ No newline at end of file diff --git a/test_data/blocks/QmR4SptPpdiA5yfWwdkFxFWGZN4pHAx2qGE1qzAkL1ZK2P b/test_data/blocks/QmR4SptPpdiA5yfWwdkFxFWGZN4pHAx2qGE1qzAkL1ZK2P deleted file mode 100644 index 2d09b0ae..00000000 --- a/test_data/blocks/QmR4SptPpdiA5yfWwdkFxFWGZN4pHAx2qGE1qzAkL1ZK2P +++ /dev/null @@ -1,2 +0,0 @@ - -Pc4 Pc5 Pc6 Pc7 Pc8 Pc9 Pd0 Pd1 Pd2 Pd3 Pd4 Pd5 Pd6 Pd7 Pd8 Pd9 Pe0 Pe1 Pe2 Pe3 Pe4 Pe5 Pe6 Pe7 Pe8 Pe9 Pf0 Pf1 Pf2 Pf3 Pf4 Pf5 Pf6 Pf7 Pf8 Pf9  \ No newline at end of file diff --git a/test_data/blocks/bafybeiag67bl2upfzjkvpfmrncgoky6klimtd65bniz5ovxe3ahepzjune b/test_data/blocks/bafybeiag67bl2upfzjkvpfmrncgoky6klimtd65bniz5ovxe3ahepzjune new file mode 100644 index 00000000..46f68421 Binary files /dev/null and b/test_data/blocks/bafybeiag67bl2upfzjkvpfmrncgoky6klimtd65bniz5ovxe3ahepzjune differ