--- a/components/cbor/BUILD.gn +++ b/components/cbor/BUILD.gn @@ -12,7 +12,7 @@ buildflag_header("buildflags") { # TODO(crbug.com/535682335): Remove `USE_CBOR_RUST` buildflag entirely, # unconditionally enable Rust CBOR parser, and drop `is_cronet_build` check # once Cronet supports Crubit dependencies. - flags = [ "USE_CBOR_RUST=!$is_cronet_build" ] + flags = [ "USE_CBOR_RUST=$enable_cpp_api_from_rust" ] } component("cbor") { @@ -35,7 +35,7 @@ component("cbor") { "//base", ] - if (!is_cronet_build) { + if (enable_cpp_api_from_rust) { public_deps = [ "//build/rust/crubit", "//components/cbor/rust:cbor_rust_bindings", @@ -62,7 +62,7 @@ source_set("unit_tests") { "//testing/gtest", "//third_party/fuzztest", ] - if (!is_cronet_build) { + if (enable_cpp_api_from_rust) { deps += [ "//components/cbor/rust:cbor_rust_bindings", "//components/cbor/rust:cbor_rust_unittests", --- a/components/web_package/BUILD.gn +++ b/components/web_package/BUILD.gn @@ -40,7 +40,6 @@ static_library("web_package") { "//base", "//components/base32", "//components/cbor", - "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_bindings", "//mojo/public/cpp/bindings", "//net", "//services/network/public/mojom", @@ -70,7 +69,6 @@ source_set("mojom_mapped_types") { deps = [ "//base", - "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_bindings", "//crypto", "//mojo/public/cpp/bindings", ] @@ -98,7 +96,6 @@ source_set("unit_tests") { ":web_package", "//base/test:test_support", "//components/cbor", - "//components/web_package/signed_web_bundles/rust:signed_web_bundles_rust_unittests", "//components/web_package/test_support", "//mojo/public/cpp/bindings", "//mojo/public/cpp/test_support:test_utils", --- a/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc +++ b/components/web_package/signed_web_bundles/ecdsa_p256_sha256_signature.cc @@ -9,7 +9,8 @@ #include "base/strings/stringprintf.h" #include "base/types/expected.h" #include "components/web_package/signed_web_bundles/ecdsa_p256_public_key.h" -#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h" +#include "crypto/keypair.h" +#include "crypto/sign.h" namespace web_package { @@ -50,8 +51,9 @@ EcdsaP256SHA256Signature::EcdsaP256SHA25 [[nodiscard]] bool EcdsaP256SHA256Signature::Verify( base::span message, const EcdsaP256PublicKey& public_key) const { - return signed_web_bundles::rust::verify_ecdsa_p256_signature( - public_key.bytes(), bytes(), message); + auto key = crypto::keypair::PublicKey::FromEcP256Point(public_key.bytes()); + return crypto::sign::Verify(crypto::sign::ECDSA_SHA256, *key, message, + bytes()); } } // namespace web_package --- a/components/web_package/signed_web_bundles/ed25519_signature.cc +++ b/components/web_package/signed_web_bundles/ed25519_signature.cc @@ -7,7 +7,6 @@ #include #include "base/strings/stringprintf.h" -#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h" #include "third_party/boringssl/src/include/openssl/curve25519.h" namespace web_package { @@ -43,8 +42,11 @@ Ed25519Signature::Ed25519Signature(std:: [[nodiscard]] bool Ed25519Signature::Verify( base::span message, const Ed25519PublicKey& public_key) const { - return signed_web_bundles::rust::verify_ed25519_signature(public_key.bytes(), - bytes(), message); + const std::array& public_key_bytes = + public_key.bytes(); + const std::array& signature_bytes = bytes(); + return ED25519_verify(message.data(), message.size(), signature_bytes.data(), + public_key_bytes.data()); } } // namespace web_package --- a/components/web_package/signed_web_bundles/integrity_block_parser.cc +++ b/components/web_package/signed_web_bundles/integrity_block_parser.cc @@ -4,17 +4,19 @@ #include "components/web_package/signed_web_bundles/integrity_block_parser.h" +#include #include -#include #include -#include "base/check.h" -#include "base/containers/span.h" +#include "base/containers/map_util.h" #include "base/functional/bind.h" #include "base/strings/stringprintf.h" +#include "base/strings/to_string.h" #include "base/types/expected.h" #include "base/types/expected_macros.h" #include "components/cbor/reader.h" +#include "components/cbor/writer.h" +#include "components/web_package/mojom/web_bundle_parser.mojom-forward.h" #include "components/web_package/mojom/web_bundle_parser.mojom.h" #include "components/web_package/signed_web_bundles/constants.h" #include "components/web_package/signed_web_bundles/ecdsa_p256_public_key.h" @@ -22,56 +24,11 @@ #include "components/web_package/signed_web_bundles/ed25519_public_key.h" #include "components/web_package/signed_web_bundles/ed25519_signature.h" #include "components/web_package/signed_web_bundles/integrity_block_attributes.h" -#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/web_package/signed_web_bundles/types.h" namespace web_package { -namespace { - -using SignatureType = signed_web_bundles::rust::SignatureType::Tag; -using signed_web_bundles::rust::parse_integrity_block; - -base::expected -CreateSignatureStackEntry( - const signed_web_bundles::rust::SignatureStackEntry& entry) { - auto parsed_sig = mojom::BundleIntegrityBlockSignatureStackEntry::New(); - - switch (entry.signature_type.tag) { - case SignatureType::Ed25519: { - ASSIGN_OR_RETURN(auto public_key, - Ed25519PublicKey::Create(entry.public_key.to_span())); - ASSIGN_OR_RETURN(auto signature, - Ed25519Signature::Create(entry.signature.to_span())); - parsed_sig->signature_info = mojom::SignatureInfo::NewEd25519( - mojom::SignatureInfoEd25519::New(public_key, signature)); - break; - } - case SignatureType::EcdsaP256SHA256: { - ASSIGN_OR_RETURN(auto public_key, - EcdsaP256PublicKey::Create(entry.public_key.to_span())); - ASSIGN_OR_RETURN(auto signature, EcdsaP256SHA256Signature::Create( - entry.signature.to_span())); - parsed_sig->signature_info = mojom::SignatureInfo::NewEcdsaP256Sha256( - mojom::SignatureInfoEcdsaP256SHA256::New(public_key, signature)); - break; - } - case SignatureType::Unknown: { - parsed_sig->signature_info = - mojom::SignatureInfo::NewUnknown(mojom::SignatureInfoUnknown::New()); - break; - } - } - - parsed_sig->attributes_cbor = - BinaryData(entry.attributes_cbor.begin(), entry.attributes_cbor.end()); - - return parsed_sig; -} - -} // namespace - IntegrityBlockParser::IntegrityBlockParser( mojom::BundleDataSource& data_source, WebBundleParser::ParseIntegrityBlockCallback callback) @@ -103,37 +60,103 @@ void IntegrityBlockParser::OnIntegrityBl RunErrorCallback("Error reading the integrity block."); return; } + // This structure is built during parsing and returned by the final callback + mojom::BundleIntegrityBlockPtr integrity_block = + mojom::BundleIntegrityBlock::New(); + + size_t consumed_bytes = 0; + cbor::Reader::DecoderError error; + cbor::Reader::Config config; + config.num_bytes_consumed = &consumed_bytes; + config.error_code_out = &error; + + // When config `bytes_consumed` are assigned the CBOR parser reads only to the + // end of a structure. It parses only Integrity Block even if Web Bundle part + // starts just after. + std::optional value = cbor::Reader::Read(*data, config); + if (!value) { + RunErrorCallback("Error parsing integrity block as CBOR: " + + std::string(cbor::Reader::ErrorCodeToString(error))); + return; + } + integrity_block->size = consumed_bytes; + + if (!value->is_array()) { + RunErrorCallback("Integrity block is not a CBOR array."); + return; + } - const auto parse_res = parse_integrity_block(*data); - if (!parse_res.has_value()) { - const auto& error = parse_res.error(); - RunErrorCallback(std::string(error.message.as_str()), - error.is_version_error - ? mojom::BundleParseErrorType::kVersionError - : mojom::BundleParseErrorType::kFormatError); + const cbor::Value::ArrayValue& top_array = value->GetArray(); + if (top_array.size() != kIntegrityBlockV2TopLevelArrayLength) { + RunErrorCallback(base::StringPrintf( + "Invalid integrity block array length: expected %u, got %zu.", + kIntegrityBlockV2TopLevelArrayLength, top_array.size())); return; } - const auto& parsed_ib = *parse_res; - auto integrity_block = mojom::BundleIntegrityBlock::New(); - integrity_block->size = parsed_ib.size; - - const std::string_view web_bundle_id_str = - parsed_ib.web_bundle_id.to_string_view(); - RETURN_IF_ERROR( - SignedWebBundleId::Create(web_bundle_id_str), - [&](std::string error) { RunErrorCallback(std::move(error)); }); - - integrity_block->attributes = - IntegrityBlockAttributes(std::string(web_bundle_id_str), - BinaryData(parsed_ib.attributes_cbor.begin(), - parsed_ib.attributes_cbor.end())); + // 1. Magic bytes + if (!top_array[0].is_bytestring() || + !std::ranges::equal(top_array[0].GetBytestring(), + kIntegrityBlockMagicBytes)) { + RunErrorCallback("Unexpected magic bytes."); + return; + } + + // 2. Version + if (!top_array[1].is_bytestring() || + !std::ranges::equal(top_array[1].GetBytestring(), + kIntegrityBlockV2VersionBytes)) { + RunErrorCallback("Unexpected version bytes.", + mojom::BundleParseErrorType::kVersionError); + return; + } - for (const auto& entry : parsed_ib.signature_stack) { + // 3. Attributes + if (!top_array[2].is_map()) { + RunErrorCallback("Integrity block attributes must be a map."); + return; + } + const cbor::Value::MapValue& attributes_map = top_array[2].GetMap(); + const cbor::Value* web_bundle_id = + base::FindOrNull(attributes_map, cbor::Value(kWebBundleIdAttributeName)); + if (!web_bundle_id || !web_bundle_id->is_string()) { + RunErrorCallback( + "`webBundleId` integrity block attribute is missing or malformed."); + return; + } + + // Check if web_bundle_id is correct + RETURN_IF_ERROR(SignedWebBundleId::Create(web_bundle_id->GetString()), + [&](const std::string& error) { RunErrorCallback(error); }); + + BinaryData attributes_cbor = *cbor::Writer::Write(top_array[2]); + integrity_block->attributes = IntegrityBlockAttributes( + web_bundle_id->GetString(), std::move(attributes_cbor)); + + // 4. Signature Stack + if (!top_array[3].is_array()) { + RunErrorCallback("Signature stack must be an array."); + return; + } + const cbor::Value::ArrayValue& signatures = top_array[3].GetArray(); + if (signatures.empty()) { + RunErrorCallback( + "The signature stack must contain at least one signature."); + return; + } + + for (const auto& signature_info_raw : signatures) { ASSIGN_OR_RETURN( - auto parsed_sig, CreateSignatureStackEntry(entry), - [&](std::string error) { RunErrorCallback(std::move(error)); }); - integrity_block->signature_stack.push_back(std::move(parsed_sig)); + auto parsed_signature_info, ParseSignatureInfo(signature_info_raw), + [&](const std::string& error) { this->RunErrorCallback(error); }); + + if (integrity_block->signature_stack.empty() && + parsed_signature_info->signature_info->is_unknown()) { + RunErrorCallback("Unknown cipher type of the first signature."); + return; + } + integrity_block->signature_stack.push_back( + std::move(parsed_signature_info)); } std::move(complete_callback_) @@ -141,13 +164,74 @@ void IntegrityBlockParser::OnIntegrityBl std::move(integrity_block), nullptr)); } +base::expected +IntegrityBlockParser::ParseSignatureInfo( + const cbor::Value& signature_info_raw) { + if (!signature_info_raw.is_array() || + signature_info_raw.GetArray().size() != 2) { + return base::unexpected( + "Each signature stack entry must contain exactly two elements."); + } + + const cbor::Value::ArrayValue& signature_info_array = + signature_info_raw.GetArray(); + if (!signature_info_array[0].is_map() || + !signature_info_array[1].is_bytestring()) { + return base::unexpected("Malformed signature stack entry."); + } + + mojom::BundleIntegrityBlockSignatureStackEntryPtr parsed_signature_info = + mojom::BundleIntegrityBlockSignatureStackEntry::New(); + parsed_signature_info->attributes_cbor = + *cbor::Writer::Write(signature_info_array[0]); + + const cbor::Value::MapValue& signature_attributes = + signature_info_array[0].GetMap(); + const BinaryData& signature_bytes = signature_info_array[1].GetBytestring(); + + const cbor::Value* ed25519_key = base::FindOrNull( + signature_attributes, cbor::Value(kEd25519PublicKeyAttributeName)); + const cbor::Value* ecdsa_key = base::FindOrNull( + signature_attributes, cbor::Value(kEcdsaP256PublicKeyAttributeName)); + + if (ed25519_key && ecdsa_key) { + return base::unexpected("Multiple key types for one signature."); + } else if (ed25519_key && !ed25519_key->is_bytestring()) { + return base::unexpected("Invalid ED25519 key."); + } else if (ecdsa_key && !ecdsa_key->is_bytestring()) { + return base::unexpected("Invalid ECDSA key."); + + } else if (ed25519_key && ed25519_key->is_bytestring()) { + ASSIGN_OR_RETURN(auto public_key, + Ed25519PublicKey::Create(ed25519_key->GetBytestring())); + ASSIGN_OR_RETURN(auto signature, Ed25519Signature::Create(signature_bytes)); + parsed_signature_info->signature_info = mojom::SignatureInfo::NewEd25519( + mojom::SignatureInfoEd25519::New(public_key, signature)); + + } else if (ecdsa_key && ecdsa_key->is_bytestring()) { + ASSIGN_OR_RETURN(auto public_key, + EcdsaP256PublicKey::Create(ecdsa_key->GetBytestring())); + ASSIGN_OR_RETURN(auto signature, + EcdsaP256SHA256Signature::Create(signature_bytes)); + parsed_signature_info->signature_info = + mojom::SignatureInfo::NewEcdsaP256Sha256( + mojom::SignatureInfoEcdsaP256SHA256::New(public_key, signature)); + + } else { + parsed_signature_info->signature_info = + mojom::SignatureInfo::NewUnknown(mojom::SignatureInfoUnknown::New()); + } + + return parsed_signature_info; +} + void IntegrityBlockParser::RunErrorCallback( - std::string message, + const std::string& message, mojom::BundleParseErrorType error_type) { std::move(complete_callback_) - .Run(base::BindOnce(std::move(result_callback_), nullptr, - mojom::BundleIntegrityBlockParseError::New( - error_type, std::move(message)))); + .Run(base::BindOnce( + std::move(result_callback_), nullptr, + mojom::BundleIntegrityBlockParseError::New(error_type, message))); } } // namespace web_package --- a/components/web_package/signed_web_bundles/integrity_block_parser.h +++ b/components/web_package/signed_web_bundles/integrity_block_parser.h @@ -5,13 +5,8 @@ #ifndef COMPONENTS_WEB_PACKAGE_SIGNED_WEB_BUNDLES_INTEGRITY_BLOCK_PARSER_H_ #define COMPONENTS_WEB_PACKAGE_SIGNED_WEB_BUNDLES_INTEGRITY_BLOCK_PARSER_H_ -#include -#include - -#include "base/compiler_specific.h" -#include "base/memory/raw_ref.h" -#include "base/memory/weak_ptr.h" #include "components/web_package/mojom/web_bundle_parser.mojom-forward.h" +#include "components/web_package/signed_web_bundles/integrity_block_attributes.h" #include "components/web_package/signed_web_bundles/types.h" #include "components/web_package/web_bundle_parser.h" @@ -20,7 +15,7 @@ namespace web_package { class IntegrityBlockParser : public WebBundleParser::WebBundleSectionParser { public: explicit IntegrityBlockParser( - mojom::BundleDataSource& data_source LIFETIME_BOUND, + mojom::BundleDataSource& data_source, WebBundleParser::ParseIntegrityBlockCallback callback); IntegrityBlockParser(const IntegrityBlockParser&) = delete; @@ -35,7 +30,10 @@ class IntegrityBlockParser : public WebB private: void OnIntegrityBlockRead(const std::optional& data); - void RunErrorCallback(std::string message, + base::expected + ParseSignatureInfo(const cbor::Value& attributes_map); + + void RunErrorCallback(const std::string& message, mojom::BundleParseErrorType error_type = mojom::BundleParseErrorType::kFormatError); --- a/components/web_package/signed_web_bundles/rust/BUILD.gn +++ b/components/web_package/signed_web_bundles/rust/BUILD.gn @@ -10,7 +10,6 @@ rust_static_library("signed_web_bundles_ sources = [ "constants.rs", "integrity_block.rs", - "signature_verifier.rs", "types.rs", crate_root, ] --- a/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc +++ b/components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.cc @@ -20,14 +20,17 @@ #include "base/task/thread_pool.h" #include "base/types/expected.h" #include "base/types/expected_macros.h" +#include "components/cbor/values.h" +#include "components/cbor/writer.h" +#include "components/web_package/signed_web_bundles/constants.h" #include "components/web_package/signed_web_bundles/identity_validator.h" #include "components/web_package/signed_web_bundles/integrity_block_parser.h" -#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_integrity_block.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_signature_stack.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_signature_stack_entry.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_utils.h" +#include "crypto/hash.h" #include "third_party/abseil-cpp/absl/functional/overload.h" #include "third_party/boringssl/src/include/openssl/sha.h" @@ -37,10 +40,32 @@ namespace { std::vector CreateIntegrityBlockCbor( const SignedWebBundleIntegrityBlock& integrity_block) { - auto ib_cbor_rust = - signed_web_bundles::rust::create_empty_integrity_block_cbor( - integrity_block.attributes_cbor()); - return std::vector(ib_cbor_rust.begin(), ib_cbor_rust.end()); + // This function looks like it should use a cbor::Value::ArrayValue to build + // the outer array, but it can't: one of the elements is a pre-encoded CBOR + // value which we can't safely decode because it's untrusted input. This is + // obviously undesirable, because there's no guarantee at all that the + // pre-encoded value is actually valid CBOR. + // + // TODO(https://crbug.com/454485901): once there's a memory-safe CBOR parser, + // re-parse the pre-encoded value, then re-encode it here instead of + // constructing a CBOR array by hand so that we're guaranteed that the result + // of this function is valid. + std::vector ib_cbor; + + // 0x84 is the encoding byte for an array of length 4. + ib_cbor.push_back(0x84); + base::Extend(ib_cbor, + *cbor::Writer::Write(cbor::Value(kIntegrityBlockMagicBytes))); + base::Extend(ib_cbor, *cbor::Writer::Write( + cbor::Value(kIntegrityBlockV2VersionBytes))); + // We cannot parse `attributes().cbor()` back to a cbor::Value as they + // technically represent untrusted input. + base::Extend(ib_cbor, integrity_block.attributes_cbor()); + // Encode an empty signature array. + base::Extend(ib_cbor, + *cbor::Writer::Write(cbor::Value(cbor::Value::ArrayValue()))); + + return ib_cbor; } base::expected @@ -104,7 +129,7 @@ SignedWebBundleSignatureVerifier::Calcul return base::unexpected(base::File::ErrorToString(file.GetLastFileError())); } - signed_web_bundles::rust::Sha512Hasher hasher; + crypto::hash::Hasher hash(crypto::hash::kSha512); // Calculate the hash of the Signed Web Bundle excluding its integrity block. // The file might be too big to read it into memory all at once, which is why @@ -121,14 +146,15 @@ SignedWebBundleSignatureVerifier::Calcul base::File::ErrorToString(file.GetLastFileError())); } data.resize(*bytes_read); - hasher.update(data); + hash.Update(data); if (!base::CheckAdd(offset, *bytes_read).AssignIfValid(&offset)) { return base::unexpected("The Signed Web Bundle is too large."); } } - SHA512Digest digest = std::move(hasher).finish(); + SHA512Digest digest; + hash.Finish(digest); return digest; } --- a/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc +++ b/components/web_package/signed_web_bundles/signed_web_bundle_utils.cc @@ -5,18 +5,37 @@ #include "components/web_package/signed_web_bundles/signed_web_bundle_utils.h" #include -#include -#include "components/web_package/signed_web_bundles/rust/signed_web_bundles_rust.h" +#include "base/containers/extend.h" +#include "base/containers/span.h" +#include "base/containers/span_writer.h" namespace web_package { +namespace { + +void AddItemToPayload(std::vector& payload, + base::span item) { + // Each item that is part of the payload is prefixed with its length encoded + // as a 64 bit unsigned integer. + std::array length; + auto writer = base::SpanWriter(base::span(length)); + CHECK(writer.WriteU64BigEndian(item.size())); + + base::Extend(payload, base::span(length)); + base::Extend(payload, item); +} + +} // namespace + std::vector CreateSignaturePayload( const SignedWebBundleSignatureData& data) { - auto payload_rust = signed_web_bundles::rust::create_signature_payload( - data.unsigned_web_bundle_hash, data.integrity_block_cbor, - data.attributes_cbor); - return std::vector(payload_rust.begin(), payload_rust.end()); + std::vector payload; + AddItemToPayload(payload, data.unsigned_web_bundle_hash); + AddItemToPayload(payload, data.integrity_block_cbor); + AddItemToPayload(payload, data.attributes_cbor); + + return payload; } } // namespace web_package --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn @@ -186,6 +186,18 @@ group("make_platform_generated") { ] } +rust_static_library("font_format_check") { + allow_unsafe = true # Needed for FFI that underpins the `cxx` crate. + crate_root = "fonts/opentype/format_check.rs" + sources = [ crate_root ] + cxx_bindings = [ crate_root ] + deps = [ + "//third_party/rust/font_types/v0_12:lib", + "//third_party/rust/read_fonts/v0_43:lib", + "//third_party/rust/skrifa/v0_46:lib", + ] +} + rust_static_library("rustfft_ffi") { allow_unsafe = true # Needed for FFI that underpins the `cxx` crate. crate_root = "audio/rustfft_ffi.rs" @@ -712,8 +724,6 @@ component("platform") { "fonts/generic_font_family_settings.cc", "fonts/generic_font_family_settings.h", "fonts/glyph_metrics_map.h", - "fonts/ift/ift_patcher.cc", - "fonts/ift/ift_patcher.h", "fonts/opentype/color_table_lookup.cc", "fonts/opentype/color_table_lookup.h", "fonts/opentype/font_format_check.cc", @@ -1792,7 +1802,6 @@ component("platform") { ":allow_discouraged_type", ":blink_platform_public_deps", ":platform_export", - "//build/rust/crubit", "//components/language_detection/core", "//gpu/command_buffer/client:raster_interface", "//media/capture:capture_lib", @@ -1819,9 +1828,8 @@ component("platform") { "//ui/native_theme/features", ] deps = [ + ":font_format_check", ":rustfft_ffi", - "fonts:font_format_bindings", - "fonts:ift_patcher_bindings", "//base:base_static", "//base/allocator:buildflags", "//build:chromecast_buildflags", --- a/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc +++ b/third_party/blink/renderer/platform/fonts/opentype/font_format_check.cc @@ -7,6 +7,7 @@ #include "base/containers/span.h" #include "base/containers/span_rust.h" #include "base/numerics/byte_conversions.h" +#include "third_party/blink/renderer/platform/fonts/opentype/format_check.rs.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -14,37 +15,35 @@ namespace blink { FontFormatCheck::FontFormatCheck(sk_sp sk_data) - : format_info_(font_format::get_font_format_info( + : format_info_(font_format_check::get_font_format_info( base::SpanToRustSlice(sk_data->byteSpan()))) {} -FontFormatCheck::~FontFormatCheck() = default; - bool FontFormatCheck::IsVariableFont() const { - return font_format::is_variable(format_info_); + return font_format_check::is_variable(*format_info_); } bool FontFormatCheck::IsCbdtCblcColorFont() const { - return font_format::is_cbdt_cblc(format_info_); + return font_format_check::is_cbdt_cblc(*format_info_); } bool FontFormatCheck::IsEbdtEblcMonochromeFont() const { - return font_format::is_ebdt_eblc(format_info_); + return font_format_check::is_ebdt_eblc(*format_info_); } bool FontFormatCheck::IsColrCpalColorFontV0() const { - return font_format::is_colrv0(format_info_); + return font_format_check::is_colrv0(*format_info_); } bool FontFormatCheck::IsColrCpalColorFontV1() const { - return font_format::is_colrv1(format_info_); + return font_format_check::is_colrv1(*format_info_); } bool FontFormatCheck::IsSbixColorFont() const { - return font_format::is_sbix(format_info_); + return font_format_check::is_sbix(*format_info_); } bool FontFormatCheck::IsCff2OutlineFont() const { - return font_format::is_cff2(format_info_); + return font_format_check::is_cff2(*format_info_); } bool FontFormatCheck::IsVariableColrV0Font() const { @@ -58,7 +57,7 @@ bool FontFormatCheck::IsColorFont() cons bool FontFormatCheck::IsAvar2Font() const { return RuntimeEnabledFeatures::FontFormatAvar2Enabled() && - font_format::is_avar2(format_info_); + font_format_check::is_avar2(*format_info_); } FontFormatCheck::VariableFontSubType FontFormatCheck::ProbeVariableFont( --- a/third_party/blink/renderer/platform/fonts/opentype/font_format_check.h +++ b/third_party/blink/renderer/platform/fonts/opentype/font_format_check.h @@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_FONT_FORMAT_CHECK_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_FONT_FORMAT_CHECK_H_ -#include "third_party/blink/renderer/platform/fonts/font_format.h" +#include "third_party/blink/renderer/platform/fonts/opentype/format_check.rs.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/skia/include/core/SkData.h" @@ -19,7 +19,7 @@ class PLATFORM_EXPORT FontFormatCheck { public: explicit FontFormatCheck(sk_sp); - virtual ~FontFormatCheck(); + virtual ~FontFormatCheck() = default; virtual bool IsVariableFont() const; virtual bool IsCbdtCblcColorFont() const; virtual bool IsEbdtEblcMonochromeFont() const; @@ -46,7 +46,7 @@ class PLATFORM_EXPORT FontFormatCheck { enum class COLRVersion { kCOLRV0, kCOLRV1, kNoCOLR }; private: - font_format::FontFormatInfo format_info_; + rust::Box format_info_; }; } // namespace blink --- a/third_party/blink/renderer/platform/fonts/opentype/format_check.rs +++ b/third_party/blink/renderer/platform/fonts/opentype/format_check.rs @@ -23,7 +23,7 @@ pub struct FontFormatInfo { format_flags: Option, } -pub fn get_font_format_info(font_bytes: &[u8]) -> FontFormatInfo { +pub fn get_font_format_info(font_bytes: &[u8]) -> Box { let file_ref = make_font_ref_internal(font_bytes, 0); match file_ref { @@ -32,11 +32,11 @@ pub fn get_font_format_info(font_bytes: font.table_directory().table_records().iter().map(|e| e.tag()).collect(); let color_version = get_colr_version(&font); let avar_version = get_avar_version(&font); - FontFormatInfo { + Box::new(FontFormatInfo { format_flags: Some(FontFormatFlags { table_tags, color_version, avar_version }), - } + }) } - _ => FontFormatInfo::default(), + _ => Box::new(FontFormatInfo::default()), } } @@ -44,10 +44,10 @@ fn get_colr_version(font_ref: &FontRef) Some(font_ref.colr().ok()?.version()) } -pub fn is_colrv1(format_info: &FontFormatInfo) -> bool { +fn is_colrv1(format_info: &FontFormatInfo) -> bool { matches!(&format_info.format_flags, Some(FontFormatFlags { color_version: Some(1), .. }),) } -pub fn is_colrv0(format_info: &FontFormatInfo) -> bool { +fn is_colrv0(format_info: &FontFormatInfo) -> bool { matches!(&format_info.format_flags, Some(FontFormatFlags { color_version: Some(0), .. }),) } @@ -56,7 +56,7 @@ fn get_avar_version(font_ref: &FontRef) Some((version.major, version.minor)) } -pub fn is_avar2(format_info: &FontFormatInfo) -> bool { +fn is_avar2(format_info: &FontFormatInfo) -> bool { matches!(&format_info.format_flags, Some(FontFormatFlags { avar_version: Some((2, _)), .. }),) } @@ -69,22 +69,39 @@ fn has_tags(format_info: &FontFormatInfo } } -pub fn is_variable(format_info: &FontFormatInfo) -> bool { +fn is_variable(format_info: &FontFormatInfo) -> bool { has_tags(format_info, &[Tag::new(b"fvar")]) } -pub fn is_sbix(format_info: &FontFormatInfo) -> bool { +fn is_sbix(format_info: &FontFormatInfo) -> bool { has_tags(format_info, &[Tag::new(b"sbix")]) } -pub fn is_cbdt_cblc(format_info: &FontFormatInfo) -> bool { +fn is_cbdt_cblc(format_info: &FontFormatInfo) -> bool { has_tags(format_info, &[Tag::new(b"CBDT"), Tag::new(b"CBLC")]) } -pub fn is_ebdt_eblc(format_info: &FontFormatInfo) -> bool { +fn is_ebdt_eblc(format_info: &FontFormatInfo) -> bool { has_tags(format_info, &[Tag::new(b"EBDT"), Tag::new(b"EBLC")]) } -pub fn is_cff2(format_info: &FontFormatInfo) -> bool { +fn is_cff2(format_info: &FontFormatInfo) -> bool { has_tags(format_info, &[Tag::new(b"CFF2")]) } + +#[cxx::bridge(namespace = "font_format_check")] +pub mod ffi { + extern "Rust" { + type FontFormatInfo; + + fn get_font_format_info(font_bytes: &[u8]) -> Box; + fn is_colrv1(format_info: &FontFormatInfo) -> bool; + fn is_colrv0(format_info: &FontFormatInfo) -> bool; + fn is_cbdt_cblc(format_info: &FontFormatInfo) -> bool; + fn is_ebdt_eblc(format_info: &FontFormatInfo) -> bool; + fn is_variable(format_info: &FontFormatInfo) -> bool; + fn is_sbix(format_info: &FontFormatInfo) -> bool; + fn is_cff2(format_info: &FontFormatInfo) -> bool; + fn is_avar2(format_info: &FontFormatInfo) -> bool; + } +}