diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 15:28:34 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:54:51 +0000 |
commit | 2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch) | |
tree | eb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/components/services | |
parent | b014812705fc80bff0a5c120dfcef88f349816dc (diff) | |
download | qtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz |
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/services')
41 files changed, 1341 insertions, 145 deletions
diff --git a/chromium/components/services/filesystem/OWNERS b/chromium/components/services/filesystem/OWNERS index 771a70f0147..21beb1aaa89 100644 --- a/chromium/components/services/filesystem/OWNERS +++ b/chromium/components/services/filesystem/OWNERS @@ -1,5 +1,3 @@ -erg@chromium.org - per-file manifest.json=set noparent per-file manifest.json=file://ipc/SECURITY_OWNERS diff --git a/chromium/components/services/font/BUILD.gn b/chromium/components/services/font/BUILD.gn index 5ca31f1b490..a6ce90a915e 100644 --- a/chromium/components/services/font/BUILD.gn +++ b/chromium/components/services/font/BUILD.gn @@ -2,8 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/features.gni") +import("//build/config/features.gni") +import("//ppapi/buildflags/buildflags.gni") +import("//ppapi/buildflags/buildflags.gni") import("//services/service_manager/public/cpp/service.gni") import("//services/service_manager/public/service_manifest.gni") +import("//services/service_manager/public/tools/test/service_test.gni") +import("//testing/test.gni") source_set("lib") { sources = [ @@ -16,12 +22,38 @@ source_set("lib") { "//components/services/font/public/interfaces", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", + "//ppapi/buildflags:buildflags", "//services/service_manager/public/cpp", + "//ui/gfx", ] public_deps = [ "//skia", ] + + if (is_linux && enable_plugins) { + deps += [ ":ppapi_fontconfig_matching" ] + } + + if (is_linux) { + deps += [ "//base/test:fontconfig_util_linux" ] + } +} + +if (is_linux && enable_plugins) { + source_set("ppapi_fontconfig_matching") { + sources = [ + "ppapi_fontconfig_matching.cc", + "ppapi_fontconfig_matching.h", + ] + + deps = [ + "//base:base", + "//ppapi/buildflags:buildflags", + "//ppapi/c", + "//third_party/fontconfig", + ] + } } service("font_service") { @@ -41,3 +73,45 @@ service_manifest("manifest") { name = "font_service" source = "manifest.json" } + +service_test("font_service_unittests") { + sources = [ + "font_loader_test.cc", + "font_loader_test.h", + ] + + catalog = ":font_service_unittests_catalog" + + deps = [ + "//base", + "//components/services/font/public/cpp", + "//components/services/font/public/interfaces", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", + "//ppapi/buildflags:buildflags", + "//services/service_manager/public/cpp", + "//services/service_manager/public/cpp:service_test_support", + "//skia", + ] + + if (enable_plugins) { + deps += [ + "//ppapi/c", + "//third_party:freetype_harfbuzz", + ] + } + + data_deps = [ + ":font_service", + ] +} + +service_manifest("test_manifest") { + name = "font_service_unittests" + source = "test_manifest.json" +} + +catalog("font_service_unittests_catalog") { + embedded_services = [ ":test_manifest" ] + standalone_services = [ ":manifest" ] +} diff --git a/chromium/components/services/font/DEPS b/chromium/components/services/font/DEPS index dccac320689..b81f8787fc9 100644 --- a/chromium/components/services/font/DEPS +++ b/chromium/components/services/font/DEPS @@ -1,6 +1,9 @@ include_rules = [ "+services/service_manager", "+mojo/public", + "+ppapi/buildflags", + "+ppapi/c", "+skia", "+third_party/skia/include", + "+ui/gfx" ] diff --git a/chromium/components/services/font/OWNERS b/chromium/components/services/font/OWNERS index 0447911a6c3..3d43cf0bd5f 100644 --- a/chromium/components/services/font/OWNERS +++ b/chromium/components/services/font/OWNERS @@ -1,4 +1,6 @@ -erg@chromium.org +drott@chromium.org per-file manifest.json=set noparent per-file manifest.json=file://ipc/SECURITY_OWNERS +per-file test_manifest.json=set noparent +per-file test_manifest.json=file://ipc/SECURITY_OWNERS diff --git a/chromium/components/services/font/font_loader_test.cc b/chromium/components/services/font/font_loader_test.cc new file mode 100644 index 00000000000..4425736a967 --- /dev/null +++ b/chromium/components/services/font/font_loader_test.cc @@ -0,0 +1,235 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/services/font/font_loader_test.h" + +#include <utility> + +#include "base/run_loop.h" +#include "components/services/font/public/interfaces/constants.mojom.h" +#include "components/services/font/public/interfaces/font_service.mojom.h" +#include "ppapi/buildflags/buildflags.h" +#include "services/service_manager/public/cpp/connector.h" +#include "third_party/skia/include/core/SkFontStyle.h" + +#if BUILDFLAG(ENABLE_PLUGINS) +#include <ft2build.h> +#include <freetype/freetype.h> +#include "ppapi/c/private/pp_private_font_charset.h" // nogncheck +#endif + +namespace { +bool IsInTestFontDirectory(const char* path) { + const char kTestFontsDir[] = "test_fonts"; + return std::string(path).find(kTestFontsDir) != std::string::npos; +} + +#if BUILDFLAG(ENABLE_PLUGINS) +std::string GetPostscriptNameFromFile(base::File& font_file) { + int64_t file_size = font_file.GetLength(); + if (!file_size) + return ""; + + std::vector<char> file_contents; + file_contents.reserve(file_size); + CHECK_EQ(file_size, font_file.Read(0, file_contents.data(), file_size)); + std::string font_family_name; + FT_Library library; + FT_Init_FreeType(&library); + FT_Face font_face; + FT_Open_Args open_args = {FT_OPEN_MEMORY, + reinterpret_cast<FT_Byte*>(file_contents.data()), + file_size}; + CHECK_EQ(FT_Err_Ok, FT_Open_Face(library, &open_args, 0, &font_face)); + font_family_name = FT_Get_Postscript_Name(font_face); + FT_Done_Face(font_face); + FT_Done_FreeType(library); + return font_family_name; +} +#endif + +} // namespace + +namespace font_service { + +FontLoaderTest::FontLoaderTest() : ServiceTest("font_service_unittests") {} + +FontLoaderTest::~FontLoaderTest() {} + +void FontLoaderTest::SetUp() { + ServiceTest::SetUp(); + font_loader_ = std::make_unique<FontLoader>(connector()); +} + +TEST_F(FontLoaderTest, BasicMatchingTest) { + SkFontStyle styles[] = { + SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width, + SkFontStyle::kUpright_Slant), + SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width, + SkFontStyle::kUpright_Slant), + SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width, + SkFontStyle::kItalic_Slant)}; + // See kFontsConfTemplate[] in fontconfig_util_linux.cc for details of which + // fonts can be picked. Arial, Times New Roman and Courier New are aliased to + // Arimos, Tinos and Cousine ChromeOS open source alternatives when FontConfig + // is set up for testing. + std::vector<std::vector<std::string>> family_names_expected_names = { + {"Arial", "Arimo"}, + {"Times New Roman", "Tinos"}, + {"Courier New", "Cousine"}}; + for (std::vector<std::string> request_family_name : + family_names_expected_names) { + for (auto& request_style : styles) { + SkFontConfigInterface::FontIdentity font_identity; + SkFontStyle result_style; + SkString result_family_name; + font_loader()->matchFamilyName(request_family_name[0].c_str(), + request_style, &font_identity, + &result_family_name, &result_style); + EXPECT_EQ(request_family_name[1], + std::string(result_family_name.c_str())); + EXPECT_TRUE(IsInTestFontDirectory(font_identity.fString.c_str())); + EXPECT_EQ(result_style, request_style); + } + } +} + +TEST_F(FontLoaderTest, NotFoundTest) { + std::string request_family_name = {"IMPROBABLE_FONT_NAME"}; + SkFontConfigInterface::FontIdentity font_identity; + SkFontStyle result_style; + SkString result_family_name; + font_loader()->matchFamilyName(request_family_name.c_str(), SkFontStyle(), + &font_identity, &result_family_name, + &result_style); + EXPECT_EQ("", std::string(result_family_name.c_str())); + EXPECT_EQ(0u, font_identity.fID); + EXPECT_EQ("", std::string(font_identity.fString.c_str())); +} + +TEST_F(FontLoaderTest, EmptyFontName) { + std::string request_family_name = {""}; + std::string kDefaultFontName = "DejaVu Sans"; + SkFontConfigInterface::FontIdentity font_identity; + SkFontStyle result_style; + SkString result_family_name; + font_loader()->matchFamilyName(request_family_name.c_str(), SkFontStyle(), + &font_identity, &result_family_name, + &result_style); + EXPECT_EQ(kDefaultFontName, std::string(result_family_name.c_str())); + EXPECT_TRUE(IsInTestFontDirectory(font_identity.fString.c_str())); +} + +TEST_F(FontLoaderTest, CharacterFallback) { + std::pair<uint32_t, std::string> fallback_characters_families[] = { + // A selection of character hitting fonts from the third_party/test_fonts + // portfolio. + {0x662F /* CJK UNIFIED IDEOGRAPH-662F */, "Noto Sans CJK JP"}, + {0x1780 /* KHMER LETTER KA */, "Noto Sans Khmer"}, + {0xA05 /* GURMUKHI LETTER A */, "Lohit Gurmukhi"}, + {0xB85 /* TAMIL LETTER A */, "Lohit Tamil"}, + {0x904 /* DEVANAGARI LETTER SHORT A */, "Lohit Devanagari"}, + {0x985 /* BENGALI LETTER A */, "Mukti Narrow"}, + // Tests for not finding fallback: + {0x13170 /* EGYPTIAN HIEROGLYPH G042 */, ""}, + {0x1817 /* MONGOLIAN DIGIT SEVEN */, ""}}; + for (auto& character_family : fallback_characters_families) { + mojom::FontIdentityPtr font_identity; + std::string result_family_name; + bool is_bold; + bool is_italic; + font_loader()->FallbackFontForCharacter( + std::move(character_family.first), "en_US", &font_identity, + &result_family_name, &is_bold, &is_italic); + EXPECT_EQ(result_family_name, character_family.second); + EXPECT_FALSE(is_bold); + EXPECT_FALSE(is_italic); + if (character_family.second.size()) { + EXPECT_TRUE( + IsInTestFontDirectory(font_identity->str_representation.c_str())); + } else { + EXPECT_EQ(font_identity->str_representation.size(), 0u); + EXPECT_EQ(result_family_name, ""); + } + } +} + +TEST_F(FontLoaderTest, RenderStyleForStrike) { + // Use FontConfig configured test font aliases from kFontsConfTemplate in + // fontconfig_util_linux.cc. + std::pair<std::string, mojom::FontRenderStylePtr> families_styles[] = { + {"NonAntiAliasedSans", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::ON, 3, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"SlightHintedGeorgia", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::ON, 1, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"NonHintedSans", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::OFF, 0, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"AutohintedSerif", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::ON, 2, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"HintedSerif", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::ON, 2, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"FullAndAutoHintedSerif", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::ON, 3, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}, + {"SubpixelEnabledArial", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::ON, 3, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF)}, + {"SubpixelDisabledArial", + mojom::FontRenderStyle::New( + mojom::RenderStyleSwitch::ON, mojom::RenderStyleSwitch::OFF, + mojom::RenderStyleSwitch::ON, 3, mojom::RenderStyleSwitch::ON, + mojom::RenderStyleSwitch::OFF, mojom::RenderStyleSwitch::OFF)}}; + + for (auto& family_style : families_styles) { + mojom::FontRenderStylePtr result_style; + font_loader()->FontRenderStyleForStrike(std::move(family_style.first), 16, + false, false, 1.0, &result_style); + EXPECT_TRUE(result_style.Equals(family_style.second)); + } +} + +TEST_F(FontLoaderTest, PPAPIFallback) { +#if BUILDFLAG(ENABLE_PLUGINS) + std::tuple<std::string, uint32_t, std::string> family_charset_expectations[] = + { + {"", PP_PRIVATEFONTCHARSET_SHIFTJIS, "DejaVuSans"}, + {"", PP_PRIVATEFONTCHARSET_THAI, "Garuda"}, + {"", PP_PRIVATEFONTCHARSET_GB2312, "DejaVuSans"}, + {"", PP_PRIVATEFONTCHARSET_GREEK, "DejaVuSans"}, + {"Arial", PP_PRIVATEFONTCHARSET_DEFAULT, "Arimo-Regular"}, + {"Times New Roman", PP_PRIVATEFONTCHARSET_DEFAULT, "Tinos-Regular"}, + {"Courier New", PP_PRIVATEFONTCHARSET_DEFAULT, "Cousine-Regular"}, + }; + for (auto& family_charset_expectation : family_charset_expectations) { + base::File result_file; + font_loader()->MatchFontWithFallback( + std::move(std::get<0>(family_charset_expectation)), false, false, + std::move(std::get<1>(family_charset_expectation)), 0, &result_file); + EXPECT_TRUE(result_file.IsValid()); + EXPECT_EQ(GetPostscriptNameFromFile(result_file), + std::get<2>(family_charset_expectation)); + } +#endif +} + +} // namespace font_service diff --git a/chromium/components/services/font/font_loader_test.h b/chromium/components/services/font/font_loader_test.h new file mode 100644 index 00000000000..a0a4499164b --- /dev/null +++ b/chromium/components/services/font/font_loader_test.h @@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_ +#define COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_ + +#include <utility> + +#include "base/bind.h" +#include "base/macros.h" +#include "components/services/font/public/cpp/font_loader.h" +#include "components/services/font/public/interfaces/font_service.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/service_manager/public/cpp/service_test.h" + +namespace font_service { + +class FontLoaderTest : public service_manager::test::ServiceTest { + public: + FontLoaderTest(); + ~FontLoaderTest() override; + + // Overridden from service_manager::test::ServiceTest: + void SetUp() override; + + protected: + FontLoader* font_loader() { return font_loader_.get(); } + + private: + std::unique_ptr<FontLoader> font_loader_; + + DISALLOW_COPY_AND_ASSIGN(FontLoaderTest); +}; + +} // namespace font_service + +#endif // COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_ diff --git a/chromium/components/services/font/font_service_app.cc b/chromium/components/services/font/font_service_app.cc index 63ecd060702..aae40ebce0b 100644 --- a/chromium/components/services/font/font_service_app.cc +++ b/chromium/components/services/font/font_service_app.cc @@ -6,10 +6,23 @@ #include <utility> +#include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_path.h" +#include "build/build_config.h" #include "mojo/public/cpp/system/platform_handle.h" +#include "ppapi/buildflags/buildflags.h" #include "services/service_manager/public/cpp/service_context.h" +#include "ui/gfx/font_fallback_linux.h" +#include "ui/gfx/font_render_params.h" + +#if BUILDFLAG(ENABLE_PLUGINS) +#include "components/services/font/ppapi_fontconfig_matching.h" // nogncheck +#endif + +#if defined(OS_LINUX) +#include "base/test/fontconfig_util_linux.h" +#endif static_assert( static_cast<uint32_t>(SkFontStyle::kUpright_Slant) == @@ -35,13 +48,47 @@ base::File GetFileForPath(const base::FilePath& path) { return file; } +int ConvertHinting(gfx::FontRenderParams::Hinting hinting) { + switch (hinting) { + case gfx::FontRenderParams::HINTING_NONE: + return 0; + case gfx::FontRenderParams::HINTING_SLIGHT: + return 1; + case gfx::FontRenderParams::HINTING_MEDIUM: + return 2; + case gfx::FontRenderParams::HINTING_FULL: + return 3; + } + NOTREACHED() << "Unexpected hinting value " << hinting; + return 0; +} + +font_service::mojom::RenderStyleSwitch ConvertSubpixelRendering( + gfx::FontRenderParams::SubpixelRendering rendering) { + switch (rendering) { + case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE: + return font_service::mojom::RenderStyleSwitch::OFF; + case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB: + case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR: + case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB: + case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR: + return font_service::mojom::RenderStyleSwitch::ON; + } + NOTREACHED() << "Unexpected subpixel rendering value " << rendering; + return font_service::mojom::RenderStyleSwitch::NO_PREFERENCE; +} + } // namespace namespace font_service { +std::unique_ptr<service_manager::Service> FontServiceApp::CreateService() { + return std::make_unique<FontServiceApp>(); +} + FontServiceApp::FontServiceApp() { registry_.AddInterface( - base::Bind(&FontServiceApp::Create, base::Unretained(this))); + base::BindRepeating(&FontServiceApp::CreateSelf, base::Unretained(this))); } FontServiceApp::~FontServiceApp() {} @@ -98,6 +145,7 @@ void FontServiceApp::MatchFamilyName(const std::string& family_name, void FontServiceApp::OpenStream(uint32_t id_number, OpenStreamCallback callback) { + DCHECK_LT(id_number, static_cast<uint32_t>(paths_.size())); base::File file; if (id_number < static_cast<uint32_t>(paths_.size())) { file = GetFileForPath(base::FilePath(paths_[id_number].c_str())); @@ -106,7 +154,76 @@ void FontServiceApp::OpenStream(uint32_t id_number, std::move(callback).Run(std::move(file)); } -void FontServiceApp::Create(mojom::FontServiceRequest request) { +void FontServiceApp::FallbackFontForCharacter( + uint32_t character, + const std::string& locale, + FallbackFontForCharacterCallback callback) { + auto fallback_font = gfx::GetFallbackFontForChar(character, locale); + int index = FindOrAddPath(SkString(fallback_font.filename.data())); + + mojom::FontIdentityPtr identity(mojom::FontIdentity::New()); + identity->id = static_cast<uint32_t>(index); + identity->ttc_index = fallback_font.ttc_index; + identity->str_representation = fallback_font.filename; + + std::move(callback).Run(std::move(identity), fallback_font.name, + fallback_font.is_bold, fallback_font.is_italic); +} + +void FontServiceApp::FontRenderStyleForStrike( + const std::string& family, + uint32_t size, + bool is_bold, + bool is_italic, + float device_scale_factor, + FontRenderStyleForStrikeCallback callback) { + gfx::FontRenderParamsQuery query; + + query.device_scale_factor = device_scale_factor; + query.families.push_back(family); + query.pixel_size = size; + query.style = is_italic ? gfx::Font::ITALIC : 0; + query.weight = is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL; + const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, nullptr); + + mojom::FontRenderStylePtr font_render_style(mojom::FontRenderStyle::New( + params.use_bitmaps ? mojom::RenderStyleSwitch::ON + : mojom::RenderStyleSwitch::OFF, + params.autohinter ? mojom::RenderStyleSwitch::ON + : mojom::RenderStyleSwitch::OFF, + params.hinting != gfx::FontRenderParams::HINTING_NONE + ? mojom::RenderStyleSwitch::ON + : mojom::RenderStyleSwitch::OFF, + ConvertHinting(params.hinting), + params.antialiasing ? mojom::RenderStyleSwitch::ON + : mojom::RenderStyleSwitch::OFF, + ConvertSubpixelRendering(params.subpixel_rendering), + params.subpixel_positioning ? mojom::RenderStyleSwitch::ON + : mojom::RenderStyleSwitch::OFF)); + std::move(callback).Run(std::move(font_render_style)); +} + +void FontServiceApp::MatchFontWithFallback( + const std::string& family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallbackFamilyType, + MatchFontWithFallbackCallback callback) { +#if BUILDFLAG(ENABLE_PLUGINS) + base::File matched_font_file; + int font_file_descriptor = MatchFontFaceWithFallback( + family, is_bold, is_italic, charset, fallbackFamilyType); + matched_font_file = base::File(font_file_descriptor); + if (!matched_font_file.IsValid()) + matched_font_file = base::File(); + std::move(callback).Run(std::move(matched_font_file)); +#else + NOTREACHED(); +#endif +} + +void FontServiceApp::CreateSelf(mojom::FontServiceRequest request) { bindings_.AddBinding(this, std::move(request)); } diff --git a/chromium/components/services/font/font_service_app.h b/chromium/components/services/font/font_service_app.h index ce0fa7c3b49..9256a46cc51 100644 --- a/chromium/components/services/font/font_service_app.h +++ b/chromium/components/services/font/font_service_app.h @@ -23,6 +23,10 @@ class FontServiceApp : public service_manager::Service, FontServiceApp(); ~FontServiceApp() override; + static std::unique_ptr<service_manager::Service> CreateService(); + + void CreateSelf(mojom::FontServiceRequest request); + private: // service_manager::Service: void OnStart() override; @@ -35,9 +39,23 @@ class FontServiceApp : public service_manager::Service, mojom::TypefaceStylePtr requested_style, MatchFamilyNameCallback callback) override; void OpenStream(uint32_t id_number, OpenStreamCallback callback) override; - - void Create(mojom::FontServiceRequest request); - + void FallbackFontForCharacter( + uint32_t character, + const std::string& locale, + FallbackFontForCharacterCallback callback) override; + void FontRenderStyleForStrike( + const std::string& family, + uint32_t size, + bool italic, + bool bold, + float device_scale_factor, + FontRenderStyleForStrikeCallback callback) override; + void MatchFontWithFallback(const std::string& family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallbackFamilyType, + MatchFontWithFallbackCallback callback) override; int FindOrAddPath(const SkString& path); service_manager::BinderRegistry registry_; diff --git a/chromium/components/services/font/manifest.json b/chromium/components/services/font/manifest.json index 434a7ff30d7..77f1006edb7 100644 --- a/chromium/components/services/font/manifest.json +++ b/chromium/components/services/font/manifest.json @@ -5,10 +5,10 @@ "interface_provider_specs": { "service_manager:connector": { "provides": { - "app": [ "font_service.mojom.FontService" ] + "font_service": [ "font_service.mojom.FontService" ] }, "requires": { - "*": [ "app" ] + "service_manager": [ "service_manager:all_users" ] } } } diff --git a/chromium/components/services/font/ppapi_fontconfig_matching.cc b/chromium/components/services/font/ppapi_fontconfig_matching.cc new file mode 100644 index 00000000000..42f40e7469c --- /dev/null +++ b/chromium/components/services/font/ppapi_fontconfig_matching.cc @@ -0,0 +1,262 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/services/font/ppapi_fontconfig_matching.h" + +#include <fcntl.h> +#include <fontconfig/fontconfig.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <string> + +#include "base/posix/eintr_wrapper.h" +#include "base/strings/string_util.h" + +#include "ppapi/c/private/pp_private_font_charset.h" +#include "ppapi/c/trusted/ppb_browser_font_trusted.h" + +namespace { + +// MSCharSetToFontconfig translates a Microsoft charset identifier to a +// fontconfig language set by appending to |langset|. +// Returns true if |langset| is Latin/Greek/Cyrillic. +bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) { + // We have need to translate raw fdwCharSet values into terms that + // fontconfig can understand. (See the description of fdwCharSet in the MSDN + // documentation for CreateFont: + // http://msdn.microsoft.com/en-us/library/dd183499(VS.85).aspx ) + // + // Although the argument is /called/ 'charset', the actual values conflate + // character sets (which are sets of Unicode code points) and character + // encodings (which are algorithms for turning a series of bits into a + // series of code points.) Sometimes the values will name a language, + // sometimes they'll name an encoding. In the latter case I'm assuming that + // they mean the set of code points in the domain of that encoding. + // + // fontconfig deals with ISO 639-1 language codes: + // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + // + // So, for each of the documented fdwCharSet values I've had to take a + // guess at the set of ISO 639-1 languages intended. + + bool is_lgc = false; + switch (fdwCharSet) { + case PP_PRIVATEFONTCHARSET_ANSI: + // These values I don't really know what to do with, so I'm going to map + // them to English also. + case PP_PRIVATEFONTCHARSET_DEFAULT: + case PP_PRIVATEFONTCHARSET_MAC: + case PP_PRIVATEFONTCHARSET_OEM: + case PP_PRIVATEFONTCHARSET_SYMBOL: + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en")); + break; + case PP_PRIVATEFONTCHARSET_BALTIC: + // The three baltic languages. + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt")); + break; + case PP_PRIVATEFONTCHARSET_CHINESEBIG5: + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw")); + break; + case PP_PRIVATEFONTCHARSET_GB2312: + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn")); + break; + case PP_PRIVATEFONTCHARSET_EASTEUROPE: + // A scattering of eastern European languages. + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu")); + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr")); + break; + case PP_PRIVATEFONTCHARSET_GREEK: + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el")); + break; + case PP_PRIVATEFONTCHARSET_HANGUL: + case PP_PRIVATEFONTCHARSET_JOHAB: + // Korean + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko")); + break; + case PP_PRIVATEFONTCHARSET_RUSSIAN: + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru")); + break; + case PP_PRIVATEFONTCHARSET_SHIFTJIS: + // Japanese + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja")); + break; + case PP_PRIVATEFONTCHARSET_TURKISH: + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr")); + break; + case PP_PRIVATEFONTCHARSET_VIETNAMESE: + is_lgc = true; + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi")); + break; + case PP_PRIVATEFONTCHARSET_ARABIC: + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar")); + break; + case PP_PRIVATEFONTCHARSET_HEBREW: + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he")); + break; + case PP_PRIVATEFONTCHARSET_THAI: + FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th")); + break; + // default: + // Don't add any languages in that case that we don't recognise the + // constant. + } + return is_lgc; +} + +} // namespace + +namespace font_service { + +int MatchFontFaceWithFallback(const std::string& face, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallback_family) { + FcLangSet* langset = FcLangSetCreate(); + bool is_lgc = MSCharSetToFontconfig(langset, charset); + FcPattern* pattern = FcPatternCreate(); + FcPatternAddString(pattern, FC_FAMILY, + reinterpret_cast<const FcChar8*>(face.c_str())); + + // TODO(thestig) Check if we can access Chrome's per-script font preference + // here and select better default fonts for non-LGC case. + std::string generic_font_name; + if (is_lgc) { + switch (fallback_family) { + case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF: + generic_font_name = "Times New Roman"; + break; + case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF: + generic_font_name = "Arial"; + break; + case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE: + generic_font_name = "Courier New"; + break; + } + } + if (!generic_font_name.empty()) { + const FcChar8* fc_generic_font_name = + reinterpret_cast<const FcChar8*>(generic_font_name.c_str()); + FcPatternAddString(pattern, FC_FAMILY, fc_generic_font_name); + } + + if (is_bold) + FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); + if (is_italic) + FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); + FcPatternAddLangSet(pattern, FC_LANG, langset); + FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcResult result; + FcFontSet* font_set = FcFontSort(nullptr, pattern, 0, nullptr, &result); + int font_fd = -1; + int good_enough_index = -1; + bool good_enough_index_set = false; + + if (font_set) { + for (int i = 0; i < font_set->nfont; ++i) { + FcPattern* current = font_set->fonts[i]; + + // Older versions of fontconfig have a bug where they cannot select + // only scalable fonts so we have to manually filter the results. + FcBool is_scalable; + if (FcPatternGetBool(current, FC_SCALABLE, 0, &is_scalable) != + FcResultMatch || + !is_scalable) { + continue; + } + + FcChar8* c_filename; + if (FcPatternGetString(current, FC_FILE, 0, &c_filename) != + FcResultMatch) { + continue; + } + + // We only want to return sfnt (TrueType) based fonts. We don't have a + // very good way of detecting this so we'll filter based on the + // filename. + bool is_sfnt = false; + static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc", + ""}; + for (size_t j = 0;; j++) { + if (kSFNTExtensions[j][0] == 0) { + // None of the extensions matched. + break; + } + if (base::EndsWith(std::string(reinterpret_cast<char*>(c_filename)), + kSFNTExtensions[j], base::CompareCase::SENSITIVE)) { + is_sfnt = true; + break; + } + } + + if (!is_sfnt) + continue; + + // This font is good enough to pass muster, but we might be able to do + // better with subsequent ones. + if (!good_enough_index_set) { + good_enough_index = i; + good_enough_index_set = true; + } + + FcValue matrix; + bool have_matrix = FcPatternGet(current, FC_MATRIX, 0, &matrix) == 0; + + if (is_italic && have_matrix) { + // we asked for an italic font, but fontconfig is giving us a + // non-italic font with a transformation matrix. + continue; + } + + FcValue embolden; + const bool have_embolden = + FcPatternGet(current, FC_EMBOLDEN, 0, &embolden) == 0; + + if (is_bold && have_embolden) { + // we asked for a bold font, but fontconfig gave us a non-bold font + // and asked us to apply fake bolding. + continue; + } + + font_fd = + HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY)); + if (font_fd >= 0) + break; + } + } + + if (font_fd == -1 && good_enough_index_set) { + // We didn't find a font that we liked, so we fallback to something + // acceptable. + FcPattern* current = font_set->fonts[good_enough_index]; + FcChar8* c_filename; + FcPatternGetString(current, FC_FILE, 0, &c_filename); + font_fd = HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY)); + } + + if (font_set) + FcFontSetDestroy(font_set); + FcPatternDestroy(pattern); + + return font_fd; +} + +} // namespace font_service diff --git a/chromium/components/services/font/ppapi_fontconfig_matching.h b/chromium/components/services/font/ppapi_fontconfig_matching.h new file mode 100644 index 00000000000..0eedf196ffe --- /dev/null +++ b/chromium/components/services/font/ppapi_fontconfig_matching.h @@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SERVICES_FONT_PPAPI_FONTCONFIG_MATCHING_H_ +#define COMPONENTS_SERVICES_FONT_PPAPI_FONTCONFIG_MATCHING_H_ + +#include <stdint.h> +#include "base/macros.h" +#include "build/build_config.h" +#include "ppapi/buildflags/buildflags.h" + +#include <string> + +#if !BUILDFLAG(ENABLE_PLUGINS) +#error "Plugins should be enabled when including " ## __FILE__ +#endif + +namespace font_service { + +int MatchFontFaceWithFallback(const std::string& face, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallback_family); + +} // namespace font_service + +#endif // COMPONENTS_SERVICES_FONT_PPAPI_FONTCONFIG_MATCHING_H_ diff --git a/chromium/components/services/font/public/cpp/font_loader.cc b/chromium/components/services/font/public/cpp/font_loader.cc index 618c22f73a8..4974393ebb4 100644 --- a/chromium/components/services/font/public/cpp/font_loader.cc +++ b/chromium/components/services/font/public/cpp/font_loader.cc @@ -9,13 +9,14 @@ #include "base/bind.h" #include "base/trace_event/trace_event.h" #include "components/services/font/public/cpp/font_service_thread.h" +#include "components/services/font/public/interfaces/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" namespace font_service { FontLoader::FontLoader(service_manager::Connector* connector) { mojom::FontServicePtr font_service; - connector->BindInterface("font_service", &font_service); + connector->BindInterface(font_service::mojom::kServiceName, &font_service); thread_ = new internal::FontServiceThread(std::move(font_service)); } @@ -66,6 +67,41 @@ SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) { } } +// Additional cross-thread accessible methods. +bool FontLoader::FallbackFontForCharacter( + uint32_t character, + std::string locale, + mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic) { + return thread_->FallbackFontForCharacter(character, std::move(locale), + out_font_identity, out_family_name, + out_is_bold, out_is_italic); +} + +bool FontLoader::FontRenderStyleForStrike( + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + mojom::FontRenderStylePtr* out_font_render_style) { + return thread_->FontRenderStyleForStrike(std::move(family), size, is_italic, + is_bold, device_scale_factor, + out_font_render_style); +} + +void FontLoader::MatchFontWithFallback(std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallback_family_type, + base::File* out_font_file_handle) { + thread_->MatchFontWithFallback(std::move(family), is_bold, is_italic, charset, + fallback_family_type, out_font_file_handle); +} + void FontLoader::OnMappedFontFileDestroyed(internal::MappedFontFile* f) { TRACE_EVENT1("font_loader", "FontLoader::OnMappedFontFileDestroyed", "identity", f->font_id()); diff --git a/chromium/components/services/font/public/cpp/font_loader.h b/chromium/components/services/font/public/cpp/font_loader.h index 7f9d7d22e00..4eebdeac1f9 100644 --- a/chromium/components/services/font/public/cpp/font_loader.h +++ b/chromium/components/services/font/public/cpp/font_loader.h @@ -49,6 +49,35 @@ class FontLoader : public SkFontConfigInterface, SkFontStyle* out_style) override; SkStreamAsset* openStream(const FontIdentity& identity) override; + // Additional cross-thread accessible methods below. + + // Out parameters are only guaranteed to be initialized when method returns + // true. + bool FallbackFontForCharacter(uint32_t character, + std::string locale, + mojom::FontIdentityPtr* out_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic); + // Out parameters are only guaranteed to be initialized when method returns + // true. + bool FontRenderStyleForStrike( + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + mojom::FontRenderStylePtr* out_font_render_style); + // Out parameter out_font_file_handle should always be an opened file handle + // to a matched or default font file. out_font_file_handle is a default + // initialized base::File on error. + void MatchFontWithFallback(std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallbackFamilyType, + base::File* out_font_file_handle); + private: // internal::MappedFontFile::Observer: void OnMappedFontFileDestroyed(internal::MappedFontFile* f) override; diff --git a/chromium/components/services/font/public/cpp/font_service_thread.cc b/chromium/components/services/font/public/cpp/font_service_thread.cc index d1ecf77b032..b4f3aa45c34 100644 --- a/chromium/components/services/font/public/cpp/font_service_thread.cc +++ b/chromium/components/services/font/public/cpp/font_service_thread.cc @@ -22,6 +22,7 @@ FontServiceThread::FontServiceThread(mojom::FontServicePtr font_service) : base::Thread(kFontThreadName), font_service_info_(font_service.PassInterface()), weak_factory_(this) { + DETACH_FROM_THREAD(thread_checker_); Start(); } @@ -36,32 +37,85 @@ bool FontServiceThread::MatchFamilyName( bool out_valid = false; // This proxies to the other thread, which proxies to mojo. Only on the reply // from mojo do we return from this. - base::WaitableEvent done_event( - base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); + base::WaitableEvent done_event; task_runner()->PostTask( FROM_HERE, - base::Bind(&FontServiceThread::MatchFamilyNameImpl, this, &done_event, - family_name, requested_style, &out_valid, out_font_identity, - out_family_name, out_style)); + base::BindOnce(&FontServiceThread::MatchFamilyNameImpl, this, &done_event, + family_name, requested_style, &out_valid, + out_font_identity, out_family_name, out_style)); done_event.Wait(); return out_valid; } +bool FontServiceThread::FallbackFontForCharacter( + uint32_t character, + std::string locale, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic) { + DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId()); + bool out_valid = false; + base::WaitableEvent done_event; + task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&FontServiceThread::FallbackFontForCharacterImpl, this, + &done_event, character, std::move(locale), &out_valid, + out_font_identity, out_family_name, out_is_bold, + out_is_italic)); + done_event.Wait(); + + return out_valid; +} + +bool FontServiceThread::FontRenderStyleForStrike( + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + font_service::mojom::FontRenderStylePtr* out_font_render_style) { + DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId()); + bool out_valid = false; + base::WaitableEvent done_event; + task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&FontServiceThread::FontRenderStyleForStrikeImpl, this, + &done_event, family, size, is_italic, is_bold, + device_scale_factor, &out_valid, out_font_render_style)); + done_event.Wait(); + return out_valid; +} + +void FontServiceThread::MatchFontWithFallback( + std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallback_family_type, + base::File* out_font_file_handle) { + DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId()); + base::WaitableEvent done_event; + task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&FontServiceThread::MatchFontWithFallbackImpl, this, + &done_event, std::move(family), is_bold, is_italic, + charset, fallback_family_type, out_font_file_handle)); + done_event.Wait(); +} + scoped_refptr<MappedFontFile> FontServiceThread::OpenStream( const SkFontConfigInterface::FontIdentity& identity) { DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId()); base::File stream_file; - // This proxies to the other thread, which proxies to mojo. Only on the reply - // from mojo do we return from this. - base::WaitableEvent done_event( - base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - task_runner()->PostTask(FROM_HERE, - base::Bind(&FontServiceThread::OpenStreamImpl, this, - &done_event, &stream_file, identity.fID)); + // This proxies to the other thread, which proxies to mojo. Only on the + // reply from mojo do we return from this. + base::WaitableEvent done_event; + task_runner()->PostTask( + FROM_HERE, base::BindOnce(&FontServiceThread::OpenStreamImpl, this, + &done_event, &stream_file, identity.fID)); done_event.Wait(); if (!stream_file.IsValid()) { @@ -79,6 +133,7 @@ scoped_refptr<MappedFontFile> FontServiceThread::OpenStream( } FontServiceThread::~FontServiceThread() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); Stop(); } @@ -90,7 +145,7 @@ void FontServiceThread::MatchFamilyNameImpl( SkFontConfigInterface::FontIdentity* out_font_identity, SkString* out_family_name, SkFontStyle* out_style) { - DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (font_service_.encountered_error()) { *out_valid = false; @@ -103,12 +158,14 @@ void FontServiceThread::MatchFamilyNameImpl( style->width = requested_style.width(); style->slant = static_cast<mojom::TypefaceSlant>(requested_style.slant()); + const char* arg_family = family_name ? family_name : ""; + pending_waitable_events_.insert(done_event); font_service_->MatchFamilyName( - family_name, std::move(style), - base::Bind(&FontServiceThread::OnMatchFamilyNameComplete, this, - done_event, out_valid, out_font_identity, out_family_name, - out_style)); + arg_family, std::move(style), + base::BindOnce(&FontServiceThread::OnMatchFamilyNameComplete, this, + done_event, out_valid, out_font_identity, out_family_name, + out_style)); } void FontServiceThread::OnMatchFamilyNameComplete( @@ -120,7 +177,7 @@ void FontServiceThread::OnMatchFamilyNameComplete( mojom::FontIdentityPtr font_identity, const std::string& family_name, mojom::TypefaceStylePtr style) { - DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); pending_waitable_events_.erase(done_event); *out_valid = !font_identity.is_null(); @@ -142,7 +199,7 @@ void FontServiceThread::OnMatchFamilyNameComplete( void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event, base::File* output_file, const uint32_t id_number) { - DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (font_service_.encountered_error()) { done_event->Signal(); return; @@ -150,18 +207,139 @@ void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event, pending_waitable_events_.insert(done_event); font_service_->OpenStream( - id_number, base::Bind(&FontServiceThread::OnOpenStreamComplete, this, - done_event, output_file)); + id_number, base::BindOnce(&FontServiceThread::OnOpenStreamComplete, this, + done_event, output_file)); } void FontServiceThread::OnOpenStreamComplete(base::WaitableEvent* done_event, base::File* output_file, base::File file) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); pending_waitable_events_.erase(done_event); *output_file = std::move(file); done_event->Signal(); } +void FontServiceThread::FallbackFontForCharacterImpl( + base::WaitableEvent* done_event, + uint32_t character, + std::string locale, + bool* out_valid, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (font_service_.encountered_error()) { + *out_valid = false; + done_event->Signal(); + return; + } + + pending_waitable_events_.insert(done_event); + font_service_->FallbackFontForCharacter( + character, std::move(locale), + base::BindOnce(&FontServiceThread::OnFallbackFontForCharacterComplete, + this, done_event, out_valid, out_font_identity, + out_family_name, out_is_bold, out_is_italic)); +} + +void FontServiceThread::OnFallbackFontForCharacterComplete( + base::WaitableEvent* done_event, + bool* out_valid, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic, + mojom::FontIdentityPtr font_identity, + const std::string& family_name, + bool is_bold, + bool is_italic) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + pending_waitable_events_.erase(done_event); + + *out_valid = !font_identity.is_null(); + if (font_identity) { + *out_font_identity = std::move(font_identity); + *out_family_name = family_name.data(); + *out_is_bold = is_bold; + *out_is_italic = is_italic; + } + done_event->Signal(); +} + +void FontServiceThread::FontRenderStyleForStrikeImpl( + base::WaitableEvent* done_event, + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + bool* out_valid, + mojom::FontRenderStylePtr* out_font_render_style) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (font_service_.encountered_error()) { + *out_valid = false; + done_event->Signal(); + return; + } + + pending_waitable_events_.insert(done_event); + font_service_->FontRenderStyleForStrike( + std::move(family), size, is_italic, is_bold, device_scale_factor, + base::BindOnce(&FontServiceThread::OnFontRenderStyleForStrikeComplete, + this, done_event, out_valid, out_font_render_style)); +} + +void FontServiceThread::OnFontRenderStyleForStrikeComplete( + base::WaitableEvent* done_event, + bool* out_valid, + mojom::FontRenderStylePtr* out_font_render_style, + mojom::FontRenderStylePtr font_render_style) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + pending_waitable_events_.erase(done_event); + + *out_valid = !font_render_style.is_null(); + if (font_render_style) { + *out_font_render_style = std::move(font_render_style); + } + done_event->Signal(); +} + +void FontServiceThread::MatchFontWithFallbackImpl( + base::WaitableEvent* done_event, + std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallback_family_type, + base::File* out_font_file_handle) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + *out_font_file_handle = base::File(); + if (font_service_.encountered_error()) { + done_event->Signal(); + return; + } + pending_waitable_events_.insert(done_event); + font_service_->MatchFontWithFallback( + family, is_bold, is_italic, charset, fallback_family_type, + base::BindOnce(&FontServiceThread::OnMatchFontWithFallbackComplete, this, + done_event, out_font_file_handle)); +} + +void FontServiceThread::OnMatchFontWithFallbackComplete( + base::WaitableEvent* done_event, + base::File* out_font_file_handle, + base::File file) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + pending_waitable_events_.erase(done_event); + + *out_font_file_handle = std::move(file); + done_event->Signal(); +} + void FontServiceThread::OnFontServiceConnectionError() { std::set<base::WaitableEvent*> events; events.swap(pending_waitable_events_); @@ -172,8 +350,8 @@ void FontServiceThread::OnFontServiceConnectionError() { void FontServiceThread::Init() { font_service_.Bind(std::move(font_service_info_)); font_service_.set_connection_error_handler( - base::Bind(&FontServiceThread::OnFontServiceConnectionError, - weak_factory_.GetWeakPtr())); + base::BindOnce(&FontServiceThread::OnFontServiceConnectionError, + weak_factory_.GetWeakPtr())); } void FontServiceThread::CleanUp() { diff --git a/chromium/components/services/font/public/cpp/font_service_thread.h b/chromium/components/services/font/public/cpp/font_service_thread.h index 2069a290492..865c587b398 100644 --- a/chromium/components/services/font/public/cpp/font_service_thread.h +++ b/chromium/components/services/font/public/cpp/font_service_thread.h @@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" +#include "base/threading/thread_checker.h" #include "components/services/font/public/interfaces/font_service.mojom.h" #include "third_party/skia/include/core/SkStream.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -45,6 +46,27 @@ class FontServiceThread : public base::Thread, scoped_refptr<MappedFontFile> OpenStream( const SkFontConfigInterface::FontIdentity& identity); + bool FallbackFontForCharacter( + uint32_t character, + std::string locale, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic); + bool FontRenderStyleForStrike( + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + font_service::mojom::FontRenderStylePtr* out_font_render_style); + void MatchFontWithFallback(std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallbackFamilyType, + base::File* out_font_file_handle); + private: friend class base::RefCountedThreadSafe<FontServiceThread>; ~FontServiceThread() override; @@ -82,6 +104,53 @@ class FontServiceThread : public base::Thread, base::File* output_file, base::File file); + void FallbackFontForCharacterImpl( + base::WaitableEvent* done_event, + uint32_t character, + std::string locale, + bool* out_is_valid, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic); + void OnFallbackFontForCharacterComplete( + base::WaitableEvent* done_event, + bool* out_valid, + font_service::mojom::FontIdentityPtr* out_font_identity, + std::string* out_family_name, + bool* out_is_bold, + bool* out_is_italic, + mojom::FontIdentityPtr font_identity, + const std::string& family_name, + bool is_bold, + bool is_italic); + + void FontRenderStyleForStrikeImpl( + base::WaitableEvent* done_event, + std::string family, + uint32_t size, + bool is_italic, + bool is_bold, + float device_scale_factor, + bool* out_valid, + mojom::FontRenderStylePtr* out_font_render_style); + void OnFontRenderStyleForStrikeComplete( + base::WaitableEvent* done_event, + bool* out_valid, + mojom::FontRenderStylePtr* out_font_render_style, + mojom::FontRenderStylePtr font_render_style); + + void MatchFontWithFallbackImpl(base::WaitableEvent* done_event, + std::string family, + bool is_bold, + bool is_italic, + uint32_t charset, + uint32_t fallbackFamilyType, + base::File* out_font_file_handle); + void OnMatchFontWithFallbackComplete(base::WaitableEvent* done_event, + base::File* out_font_file_handle, + base::File file); + // Connection to |font_service_| has gone away. Called on the background // thread. void OnFontServiceConnectionError(); @@ -98,14 +167,17 @@ class FontServiceThread : public base::Thread, // non-thread bound, and binds it to the newly created thread. mojo::InterfacePtr<mojom::FontService> font_service_; - // All WaitableEvents supplied to OpenStreamImpl() are added here while - // waiting on the response from the |font_service_| (FontService::OpenStream() - // was called, but the callback has not been processed yet). If - // |font_service_| gets an error during this time all events in - // |pending_waitable_events_| are signaled. This is necessary as when the - // pipe is closed the callbacks are never received. + // All WaitableEvents supplied to OpenStreamImpl() and the other *Impl() + // functions are added here while waiting on the response from the + // |font_service_| (FontService::OpenStream() or other such functions were + // called, but the callbacks have not been processed yet). If |font_service_| + // gets an error during this time all events in |pending_waitable_events_| are + // signaled. This is necessary as when the pipe is closed the callbacks are + // never received. std::set<base::WaitableEvent*> pending_waitable_events_; + THREAD_CHECKER(thread_checker_); + base::WeakPtrFactory<FontServiceThread> weak_factory_; DISALLOW_COPY_AND_ASSIGN(FontServiceThread); diff --git a/chromium/components/services/font/public/interfaces/font_service.mojom b/chromium/components/services/font/public/interfaces/font_service.mojom index 6359889efd3..346499fe414 100644 --- a/chromium/components/services/font/public/interfaces/font_service.mojom +++ b/chromium/components/services/font/public/interfaces/font_service.mojom @@ -30,7 +30,26 @@ struct FontIdentity { string str_representation; }; -// Loads and resolves fonts. +enum RenderStyleSwitch { + OFF = 0, + ON = 1, + NO_PREFERENCE = 2, +}; + +struct FontRenderStyle { + RenderStyleSwitch use_bitmaps; // use embedded bitmap strike if possible + RenderStyleSwitch use_autohint; // use 'auto' hinting (FreeType specific) + RenderStyleSwitch use_hinting; // hint glyphs to the pixel grid + uint8 hint_style; // level of hinting, 0..3 + RenderStyleSwitch use_antialias; // antialias glyph shapes + // use subpixel rendering (partially-filled pixels) + RenderStyleSwitch use_subpixel_rendering; + // use subpixel positioning (fractional X positions for glyphs) + RenderStyleSwitch use_subpixel_positioning; +}; + +// Loads and resolves fonts & returns additional information accessible from +// FontConfig only outside the sandbox. // // We still need to load fonts from within a sandboxed process. We set // up a service to match fonts and load them. This service needs full @@ -45,4 +64,27 @@ interface FontService { // Returns a handle to the raw font specified by |id_number|. OpenStream(uint32 id_number) => (mojo_base.mojom.File? font_handle); + + // Returns a fallback FontIdentity and Typeface style for the given character + // and locale. If no fallback font can be found, returns a null identity. + FallbackFontForCharacter(uint32 character, string locale) => + (FontIdentity? identity, + string family_name, + bool is_bold, + bool is_italic); + + // Fill out the given WebFontRenderStyle with the user's preferences for + // rendering the given font at the given size (in pixels), given weight + // (is_bold or not), and given slant (is_italic or not). + FontRenderStyleForStrike(string family, + uint32 size, + bool is_italic, + bool is_bold, + float device_scale_factor) => + (FontRenderStyle? font_render_style); + + // PPAPI Specific font call to match a font family and charset. + MatchFontWithFallback(string family, bool is_bold, bool is_italic, + uint32 charset, uint32 fallback_family_type) => + (mojo_base.mojom.File? font_file_handle); }; diff --git a/chromium/components/services/font/test_manifest.json b/chromium/components/services/font/test_manifest.json new file mode 100644 index 00000000000..a9689872f50 --- /dev/null +++ b/chromium/components/services/font/test_manifest.json @@ -0,0 +1,11 @@ +{ + "name": "font_service_unittests", + "display_name": "Font Service Unittests", + "interface_provider_specs": { + "service_manager:connector": { + "requires": { + "font_service": [ "font_service" ] + } + } + } +} diff --git a/chromium/components/services/heap_profiling/BUILD.gn b/chromium/components/services/heap_profiling/BUILD.gn index 0b98f99baed..96bfb9c24d0 100644 --- a/chromium/components/services/heap_profiling/BUILD.gn +++ b/chromium/components/services/heap_profiling/BUILD.gn @@ -36,7 +36,6 @@ static_library("heap_profiling") { deps = [ "//base", "//components/services/heap_profiling/public/cpp", - "//mojo/edk", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", "//third_party/zlib", ] diff --git a/chromium/components/services/heap_profiling/DEPS b/chromium/components/services/heap_profiling/DEPS index 6973709b170..6abb9cad06d 100644 --- a/chromium/components/services/heap_profiling/DEPS +++ b/chromium/components/services/heap_profiling/DEPS @@ -1,6 +1,5 @@ include_rules = [ "+components/services/heap_profiling/public", - "+mojo/edk/embedder", "+services/resource_coordinator/public", "+third_party/zlib/zlib.h", ] diff --git a/chromium/components/services/heap_profiling/connection_manager.cc b/chromium/components/services/heap_profiling/connection_manager.cc index 5f0797c7f2f..265db1b92f8 100644 --- a/chromium/components/services/heap_profiling/connection_manager.cc +++ b/chromium/components/services/heap_profiling/connection_manager.cc @@ -147,12 +147,8 @@ void ConnectionManager::OnNewConnection(base::ProcessId pid, // when the user is attempting to manually start profiling for processes, so // we ignore this edge case. - base::PlatformFile receiver_handle; - CHECK_EQ(MOJO_RESULT_OK, mojo::UnwrapPlatformFile( - std::move(receiver_pipe_end), &receiver_handle)); - scoped_refptr<ReceiverPipe> new_pipe = - new ReceiverPipe(mojo::edk::ScopedInternalPlatformHandle( - mojo::edk::InternalPlatformHandle(receiver_handle))); + scoped_refptr<ReceiverPipe> new_pipe = new ReceiverPipe( + mojo::UnwrapPlatformHandle(std::move(receiver_pipe_end))); // The allocation tracker will call this on a background thread, so thunk // back to the current thread with weak pointers. diff --git a/chromium/components/services/heap_profiling/connection_manager.h b/chromium/components/services/heap_profiling/connection_manager.h index c2c74dfd71b..97dd66dbb6d 100644 --- a/chromium/components/services/heap_profiling/connection_manager.h +++ b/chromium/components/services/heap_profiling/connection_manager.h @@ -21,7 +21,6 @@ #include "components/services/heap_profiling/allocation_tracker.h" #include "components/services/heap_profiling/backtrace_storage.h" #include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h" namespace base { diff --git a/chromium/components/services/heap_profiling/json_exporter_unittest.cc b/chromium/components/services/heap_profiling/json_exporter_unittest.cc index 6347b864bf5..df61b5f3329 100644 --- a/chromium/components/services/heap_profiling/json_exporter_unittest.cc +++ b/chromium/components/services/heap_profiling/json_exporter_unittest.cc @@ -30,6 +30,7 @@ using MemoryMap = std::vector<memory_instrumentation::mojom::VmRegionPtr>; static constexpr int kNoParent = -1; +#if !defined(ADDRESS_SANITIZER) // Finds the first vm region in the given periodic interval. Returns null on // failure. const base::Value* FindFirstRegionWithAnyName(const base::Value* root) { @@ -52,6 +53,7 @@ const base::Value* FindFirstRegionWithAnyName(const base::Value* root) { } return nullptr; } +#endif // !defined(ADDRESS_SANITIZER) // Looks up a given string id from the string table. Returns -1 if not found. int GetIdFromStringTable(const base::Value* strings, const char* text) { @@ -440,6 +442,10 @@ TEST(ProfilingJsonExporterTest, SimpleWithFilteredAllocations) { EXPECT_NE(-1, node_bt3); } +// GetProcessMemoryMaps iterates through every memory region, making allocations +// for each one. ASAN will potentially, for each allocation, make memory +// regions. This will cause the test to time out. +#if !defined(ADDRESS_SANITIZER) TEST(ProfilingJsonExporterTest, MemoryMaps) { AllocationEventSet events; ExportParams params; @@ -477,6 +483,7 @@ TEST(ProfilingJsonExporterTest, MemoryMaps) { EXPECT_NE(size->GetString(), ""); EXPECT_NE(size->GetString(), "0"); } +#endif // !defined(ADDRESS_SANITIZER) TEST(ProfilingJsonExporterTest, Context) { BacktraceStorage backtrace_storage; diff --git a/chromium/components/services/heap_profiling/public/cpp/BUILD.gn b/chromium/components/services/heap_profiling/public/cpp/BUILD.gn index 6c826fd2e81..acaf0c29b6f 100644 --- a/chromium/components/services/heap_profiling/public/cpp/BUILD.gn +++ b/chromium/components/services/heap_profiling/public/cpp/BUILD.gn @@ -26,7 +26,6 @@ static_library("cpp") { "//base", "//base:debugging_buildflags", "//base/allocator:buildflags", - "//mojo/edk", "//services/resource_coordinator/public/mojom:", "//services/service_manager/public/cpp", ] @@ -47,7 +46,6 @@ source_set("unit_tests") { "//base", "//base/allocator:buildflags", "//base/test:test_support", - "//mojo/edk", "//testing/gtest", ] } diff --git a/chromium/components/services/heap_profiling/public/cpp/DEPS b/chromium/components/services/heap_profiling/public/cpp/DEPS index 80d54b4be0f..0ba279aecbd 100644 --- a/chromium/components/services/heap_profiling/public/cpp/DEPS +++ b/chromium/components/services/heap_profiling/public/cpp/DEPS @@ -1,4 +1,3 @@ include_rules = [ - "+mojo/edk/embedder", "+components/services/heap_profiling/public", ] diff --git a/chromium/components/services/heap_profiling/public/cpp/allocator_shim.cc b/chromium/components/services/heap_profiling/public/cpp/allocator_shim.cc index 729d2119b41..ee956609b4a 100644 --- a/chromium/components/services/heap_profiling/public/cpp/allocator_shim.cc +++ b/chromium/components/services/heap_profiling/public/cpp/allocator_shim.cc @@ -27,6 +27,11 @@ #if defined(OS_POSIX) #include <limits.h> +#include <pthread.h> +#endif + +#if defined(OS_WIN) +#include <windows.h> #endif #if defined(OS_LINUX) || defined(OS_ANDROID) @@ -44,7 +49,57 @@ using CaptureMode = base::trace_event::AllocationContextTracker::CaptureMode; namespace heap_profiling { -// A ScopedAllowLogging instance must be instantiated in the scope of all hooks. +namespace { + +// The base implementation of TLS will leak memory if accessed during late +// stages of thread destruction. We roll our own implementation of TLS to +// prevent reentrancy. Since this only requires storing a single bit of +// information, we don't need to deal with hooking thread destruction to free +// memory, and thus avoid leaks and other issues. +#if defined(OS_WIN) +using TLSKey = DWORD; +#else +using TLSKey = pthread_key_t; +#endif + +// Holds a key to a TLS value. The TLS value (0 or 1) indicates whether the +// allocator shim is already being used on the current thread. +TLSKey g_prevent_reentrancy_key = 0; + +void InitializeReentrancyKey() { +#if defined(OS_WIN) + g_prevent_reentrancy_key = TlsAlloc(); + DCHECK_NE(TLS_OUT_OF_INDEXES, g_prevent_reentrancy_key); +#else + // Returns |0| on success. + int result = pthread_key_create(&g_prevent_reentrancy_key, nullptr); + DCHECK(!result); +#endif +} + +bool CanEnterAllocatorShim() { +#if defined(OS_WIN) + return !TlsGetValue(g_prevent_reentrancy_key); +#else + return !pthread_getspecific(g_prevent_reentrancy_key); +#endif +} + +void SetEnteringAllocatorShim(bool entering) { + void* value = entering ? reinterpret_cast<void*>(1) : nullptr; +#if defined(OS_WIN) + BOOL ret = TlsSetValue(g_prevent_reentrancy_key, value); + DPCHECK(ret); +#else + int ret = pthread_setspecific(g_prevent_reentrancy_key, value); + DCHECK_EQ(ret, 0); +#endif +} + +} // namespace + +// A ScopedAllow{Free,Alloc} instance must be instantiated in the scope of all +// hooks. // AllocatorShimLogAlloc/AllocatorShimLogFree must only be called if it // evaluates to true. // @@ -62,28 +117,42 @@ namespace heap_profiling { // The implementation of libmalloc will sometimes call malloc [from // one zone to another] - without this guard, the allocation would get two // chances of being sampled. -class ScopedAllowLogging { +class ScopedAllowFree { public: - ScopedAllowLogging() - : allowed_(LIKELY(!base::ThreadLocalStorage::HasBeenDestroyed()) && - LIKELY(!prevent_reentrancy_.Pointer()->Get())) { + ScopedAllowFree() : allowed_(LIKELY(CanEnterAllocatorShim())) { if (allowed_) - prevent_reentrancy_.Pointer()->Set(true); + SetEnteringAllocatorShim(true); } - ~ScopedAllowLogging() { + ~ScopedAllowFree() { if (allowed_) - prevent_reentrancy_.Pointer()->Set(false); + SetEnteringAllocatorShim(false); } explicit operator bool() const { return allowed_; } private: const bool allowed_; - static base::LazyInstance<base::ThreadLocalBoolean>::Leaky - prevent_reentrancy_; }; -base::LazyInstance<base::ThreadLocalBoolean>::Leaky - ScopedAllowLogging::prevent_reentrancy_; +// Allocation logging also requires use of base TLS, so we must also check that +// that is available. This means that allocations that occur after base TLS has +// been torn down will not be logged. +class ScopedAllowAlloc { + public: + ScopedAllowAlloc() + : allowed_(LIKELY(CanEnterAllocatorShim()) && + LIKELY(!base::ThreadLocalStorage::HasBeenDestroyed())) { + if (allowed_) + SetEnteringAllocatorShim(true); + } + ~ScopedAllowAlloc() { + if (allowed_) + SetEnteringAllocatorShim(false); + } + explicit operator bool() const { return allowed_; } + + private: + const bool allowed_; +}; namespace { @@ -162,14 +231,14 @@ void DestructShimState(void* shim_state) { // Technically, this code could be called after Thread destruction and we would // need to guard this with ThreadLocalStorage::HasBeenDestroyed(), but all calls -// to this are guarded behind ScopedAllowLogging, which already makes the check. +// to this are guarded behind ScopedAllowAlloc, which already makes the check. base::ThreadLocalStorage::Slot& ShimStateTLS() { static base::NoDestructor<base::ThreadLocalStorage::Slot> shim_state_tls( &DestructShimState); return *shim_state_tls; } -// We don't need to worry about re-entrancy because ScopedAllowLogging +// We don't need to worry about re-entrancy because ScopedAllowAlloc. // already guards against that. ShimState* GetShimState() { ShimState* state = static_cast<ShimState*>(ShimStateTLS().Get()); @@ -321,7 +390,7 @@ void DoSend(const void* address, #if BUILDFLAG(USE_ALLOCATOR_SHIM) void* HookAlloc(const AllocatorDispatch* self, size_t size, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; const AllocatorDispatch* const next = self->next; void* ptr = next->alloc_function(next, size, context); @@ -337,7 +406,7 @@ void* HookZeroInitAlloc(const AllocatorDispatch* self, size_t n, size_t size, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; const AllocatorDispatch* const next = self->next; void* ptr = next->alloc_zero_initialized_function(next, n, size, context); @@ -352,7 +421,7 @@ void* HookAllocAligned(const AllocatorDispatch* self, size_t alignment, size_t size, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; const AllocatorDispatch* const next = self->next; void* ptr = next->alloc_aligned_function(next, alignment, size, context); @@ -367,7 +436,7 @@ void* HookRealloc(const AllocatorDispatch* self, void* address, size_t size, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; const AllocatorDispatch* const next = self->next; void* ptr = next->realloc_function(next, address, size, context); @@ -382,7 +451,7 @@ void* HookRealloc(const AllocatorDispatch* self, } void HookFree(const AllocatorDispatch* self, void* address, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowFree allow_logging; const AllocatorDispatch* const next = self->next; next->free_function(next, address, context); @@ -404,7 +473,7 @@ unsigned HookBatchMalloc(const AllocatorDispatch* self, void** results, unsigned num_requested, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; const AllocatorDispatch* const next = self->next; unsigned count = @@ -421,7 +490,7 @@ void HookBatchFree(const AllocatorDispatch* self, void** to_be_freed, unsigned num_to_be_freed, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowFree allow_logging; const AllocatorDispatch* const next = self->next; next->batch_free_function(next, to_be_freed, num_to_be_freed, context); @@ -436,7 +505,7 @@ void HookFreeDefiniteSize(const AllocatorDispatch* self, void* ptr, size_t size, void* context) { - ScopedAllowLogging allow_logging; + ScopedAllowFree allow_logging; const AllocatorDispatch* const next = self->next; next->free_definite_size_function(next, ptr, size, context); @@ -461,28 +530,28 @@ AllocatorDispatch g_hooks = { #endif // BUILDFLAG(USE_ALLOCATOR_SHIM) void HookPartitionAlloc(void* address, size_t size, const char* type) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; if (LIKELY(allow_logging)) { AllocatorShimLogAlloc(AllocatorType::kPartitionAlloc, address, size, type); } } void HookPartitionFree(void* address) { - ScopedAllowLogging allow_logging; + ScopedAllowFree allow_logging; if (LIKELY(allow_logging)) { AllocatorShimLogFree(address); } } void HookGCAlloc(uint8_t* address, size_t size, const char* type) { - ScopedAllowLogging allow_logging; + ScopedAllowAlloc allow_logging; if (LIKELY(allow_logging)) { AllocatorShimLogAlloc(AllocatorType::kOilpan, address, size, type); } } void HookGCFree(uint8_t* address) { - ScopedAllowLogging allow_logging; + ScopedAllowFree allow_logging; if (LIKELY(allow_logging)) { AllocatorShimLogFree(address); } @@ -589,7 +658,7 @@ class FrameSerializer { } // namespace void InitTLSSlot() { - { ScopedAllowLogging allow_logging; } + InitializeReentrancyKey(); ignore_result(ShimStateTLS()); } @@ -814,6 +883,9 @@ void AllocatorShimLogAlloc(AllocatorType type, } } +// This function may be called post Chrome TLS destruction, so it must not use +// Chrome TLS. It currently uses 3 classes from Chrome: base::Lock, +// base::TimeTicks and base::ScopedPlatformFile, all of which are safe. void AllocatorShimLogFree(void* address) { SendBuffer* send_buffers = g_send_buffers.Read(); if (!send_buffers) diff --git a/chromium/components/services/heap_profiling/public/cpp/allocator_shim.h b/chromium/components/services/heap_profiling/public/cpp/allocator_shim.h index 8004d3239f1..a1fedfc7258 100644 --- a/chromium/components/services/heap_profiling/public/cpp/allocator_shim.h +++ b/chromium/components/services/heap_profiling/public/cpp/allocator_shim.h @@ -38,6 +38,7 @@ void AllocatorShimLogAlloc(AllocatorType type, size_t sz, const char* context); +// Logs a free. This must not rely on the base implementation of TLS. void AllocatorShimLogFree(void* address); // Ensures all send buffers are flushed. The given barrier ID is sent to the diff --git a/chromium/components/services/heap_profiling/public/cpp/client.cc b/chromium/components/services/heap_profiling/public/cpp/client.cc index cebff10d057..9f569812188 100644 --- a/chromium/components/services/heap_profiling/public/cpp/client.cc +++ b/chromium/components/services/heap_profiling/public/cpp/client.cc @@ -66,12 +66,8 @@ void Client::StartProfiling(mojom::ProfilingParamsPtr params) { return; started_profiling_ = true; - base::PlatformFile platform_file; - CHECK_EQ(MOJO_RESULT_OK, mojo::UnwrapPlatformFile( - std::move(params->sender_pipe), &platform_file)); - - base::ScopedPlatformFile scoped_platform_file(platform_file); - sender_pipe_.reset(new SenderPipe(std::move(scoped_platform_file))); + sender_pipe_.reset(new SenderPipe( + mojo::UnwrapPlatformHandle(std::move(params->sender_pipe)))); StreamHeader header; header.signature = kStreamSignature; diff --git a/chromium/components/services/heap_profiling/public/cpp/controller.cc b/chromium/components/services/heap_profiling/public/cpp/controller.cc index da708a320dc..afb483300bd 100644 --- a/chromium/components/services/heap_profiling/public/cpp/controller.cc +++ b/chromium/components/services/heap_profiling/public/cpp/controller.cc @@ -50,12 +50,10 @@ void Controller::StartProfilingClient(mojom::ProfilingClientPtr client, mojom::ProfilingParamsPtr params = mojom::ProfilingParams::New(); params->sampling_rate = sampling_rate_; - params->sender_pipe = - mojo::WrapPlatformFile(pipes.PassSender().release().handle); + params->sender_pipe = mojo::WrapPlatformHandle(pipes.PassSender()); params->stack_mode = stack_mode_; heap_profiling_service_->AddProfilingClient( - pid, std::move(client), - mojo::WrapPlatformFile(pipes.PassReceiver().release().handle), + pid, std::move(client), mojo::WrapPlatformHandle(pipes.PassReceiver()), process_type, std::move(params)); } diff --git a/chromium/components/services/heap_profiling/public/cpp/sender_pipe.h b/chromium/components/services/heap_profiling/public/cpp/sender_pipe.h index 97c41d42af8..a84e837108d 100644 --- a/chromium/components/services/heap_profiling/public/cpp/sender_pipe.h +++ b/chromium/components/services/heap_profiling/public/cpp/sender_pipe.h @@ -10,7 +10,7 @@ #include "base/files/platform_file.h" #include "base/macros.h" #include "base/synchronization/lock.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/public/cpp/platform/platform_handle.h" namespace heap_profiling { @@ -32,20 +32,16 @@ class SenderPipe { // |kPipeSize|. PipePair(); PipePair(PipePair&&); - mojo::edk::ScopedInternalPlatformHandle PassSender() { - return std::move(sender_); - } - mojo::edk::ScopedInternalPlatformHandle PassReceiver() { - return std::move(receiver_); - } + mojo::PlatformHandle PassSender() { return std::move(sender_); } + mojo::PlatformHandle PassReceiver() { return std::move(receiver_); } private: - mojo::edk::ScopedInternalPlatformHandle sender_; - mojo::edk::ScopedInternalPlatformHandle receiver_; + mojo::PlatformHandle sender_; + mojo::PlatformHandle receiver_; DISALLOW_COPY_AND_ASSIGN(PipePair); }; - explicit SenderPipe(base::ScopedPlatformFile file); + explicit SenderPipe(mojo::PlatformHandle handle); ~SenderPipe(); enum class Result { kSuccess, kTimeout, kError }; diff --git a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc index 363226a0447..a6bb324b351 100644 --- a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc +++ b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_posix.cc @@ -31,14 +31,13 @@ SenderPipe::PipePair::PipePair() { PCHECK(fcntl(fds[0], F_SETNOSIGPIPE, 1) == 0); PCHECK(fcntl(fds[1], F_SETNOSIGPIPE, 1) == 0); #endif - receiver_.reset(mojo::edk::InternalPlatformHandle(fds[0])); - sender_.reset(mojo::edk::InternalPlatformHandle(fds[1])); + receiver_ = mojo::PlatformHandle(base::ScopedFD(fds[0])); + sender_ = mojo::PlatformHandle(base::ScopedFD(fds[1])); } SenderPipe::PipePair::PipePair(PipePair&& other) = default; -SenderPipe::SenderPipe(base::ScopedPlatformFile file) - : file_(std::move(file)) {} +SenderPipe::SenderPipe(mojo::PlatformHandle handle) : file_(handle.TakeFD()) {} SenderPipe::~SenderPipe() = default; diff --git a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc index 3e3a14c6178..4f1b636d6b2 100644 --- a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc +++ b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_unittest.cc @@ -7,11 +7,11 @@ #include <vector> #include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/public/cpp/platform/platform_handle.h" #include "testing/gtest/include/gtest/gtest.h" -#if !defined(OS_MACOSX) -#include "mojo/edk/embedder/platform_channel_pair.h" +#if defined(OS_WIN) +#include <windows.h> #endif namespace heap_profiling { @@ -22,13 +22,10 @@ using Result = SenderPipe::Result; class SenderPipeTest : public testing::Test { public: void SetUp() override { - mojo::edk::ScopedInternalPlatformHandle write_handle; - SenderPipe::PipePair pipes; read_handle_ = pipes.PassReceiver(); - base::ScopedPlatformFile file(pipes.PassSender().release().handle); - sender_pipe_.reset(new SenderPipe(std::move(file))); + sender_pipe_.reset(new SenderPipe(pipes.PassSender())); // A large buffer for both writing and reading. buffer_.resize(64 * 1024); @@ -38,21 +35,21 @@ class SenderPipeTest : public testing::Test { void Read(int size) { #if defined(OS_POSIX) - ssize_t bytes_read = read(read_handle_.get().handle, buffer_.data(), size); + ssize_t bytes_read = read(read_handle_.GetFD().get(), buffer_.data(), size); ASSERT_EQ(size, bytes_read); #else OVERLAPPED overlapped; DWORD bytes_read = 0; memset(&overlapped, 0, sizeof(OVERLAPPED)); - BOOL result = ::ReadFile(read_handle_.get().handle, buffer_.data(), size, - &bytes_read, &overlapped); + BOOL result = ::ReadFile(read_handle_.GetHandle().Get(), buffer_.data(), + size, &bytes_read, &overlapped); ASSERT_TRUE(result); ASSERT_EQ(static_cast<DWORD>(size), bytes_read); #endif } private: - mojo::edk::ScopedInternalPlatformHandle read_handle_; + mojo::PlatformHandle read_handle_; std::unique_ptr<SenderPipe> sender_pipe_; std::vector<char> buffer_; }; diff --git a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_win.cc b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_win.cc index a12e1465563..4c137f70c8f 100644 --- a/chromium/components/services/heap_profiling/public/cpp/sender_pipe_win.cc +++ b/chromium/components/services/heap_profiling/public/cpp/sender_pipe_win.cc @@ -4,6 +4,8 @@ #include "components/services/heap_profiling/public/cpp/sender_pipe.h" +#include <windows.h> + #include "base/logging.h" #include "base/rand_util.h" #include "base/strings/stringprintf.h" @@ -69,7 +71,7 @@ SenderPipe::PipePair::PipePair() { // nothing to do with Send() timeout. nullptr); PCHECK(handle != INVALID_HANDLE_VALUE); - receiver_.reset(mojo::edk::InternalPlatformHandle(handle)); + receiver_ = mojo::PlatformHandle(base::win::ScopedHandle(handle)); // Allow the handle to be inherited by child processes. SECURITY_ATTRIBUTES security_attributes; @@ -84,19 +86,19 @@ SenderPipe::PipePair::PipePair() { SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED, nullptr); PCHECK(handle != INVALID_HANDLE_VALUE); - sender_.reset(mojo::edk::InternalPlatformHandle(handle)); + sender_ = mojo::PlatformHandle(base::win::ScopedHandle(handle)); // Since a client has connected, ConnectNamedPipe() should return zero and // GetLastError() should return ERROR_PIPE_CONNECTED. - BOOL result = ConnectNamedPipe(receiver_.get().handle, nullptr); + BOOL result = ConnectNamedPipe(receiver_.GetHandle().Get(), nullptr); DWORD error = GetLastError(); CHECK((result == 0) && (error == ERROR_PIPE_CONNECTED)); } SenderPipe::PipePair::PipePair(PipePair&& other) = default; -SenderPipe::SenderPipe(base::ScopedPlatformFile file) - : file_(std::move(file)) {} +SenderPipe::SenderPipe(mojo::PlatformHandle handle) + : file_(handle.TakeHandle()) {} SenderPipe::~SenderPipe() {} diff --git a/chromium/components/services/heap_profiling/receiver_pipe.cc b/chromium/components/services/heap_profiling/receiver_pipe.cc index a2add075b2d..1d383c592da 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe.cc +++ b/chromium/components/services/heap_profiling/receiver_pipe.cc @@ -10,8 +10,7 @@ namespace heap_profiling { -ReceiverPipeBase::ReceiverPipeBase( - mojo::edk::ScopedInternalPlatformHandle handle) +ReceiverPipeBase::ReceiverPipeBase(mojo::PlatformHandle handle) : handle_(std::move(handle)) {} ReceiverPipeBase::~ReceiverPipeBase() = default; diff --git a/chromium/components/services/heap_profiling/receiver_pipe.h b/chromium/components/services/heap_profiling/receiver_pipe.h index e4e9ee36141..d0e561506b2 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe.h +++ b/chromium/components/services/heap_profiling/receiver_pipe.h @@ -7,7 +7,7 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/public/cpp/platform/platform_handle.h" namespace base { class TaskRunner; @@ -29,7 +29,7 @@ class ReceiverPipeBase : public base::RefCountedThreadSafe<ReceiverPipeBase> { protected: friend class base::RefCountedThreadSafe<ReceiverPipeBase>; - explicit ReceiverPipeBase(mojo::edk::ScopedInternalPlatformHandle handle); + explicit ReceiverPipeBase(mojo::PlatformHandle handle); virtual ~ReceiverPipeBase(); // Callback that indicates an error has occurred and the connection should @@ -46,7 +46,7 @@ class ReceiverPipeBase : public base::RefCountedThreadSafe<ReceiverPipeBase> { scoped_refptr<base::TaskRunner> receiver_task_runner_; scoped_refptr<StreamReceiver> receiver_; - mojo::edk::ScopedInternalPlatformHandle handle_; + mojo::PlatformHandle handle_; }; } // namespace heap_profiling diff --git a/chromium/components/services/heap_profiling/receiver_pipe_posix.cc b/chromium/components/services/heap_profiling/receiver_pipe_posix.cc index 35baa5dfb91..c8cb80b8e00 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe_posix.cc +++ b/chromium/components/services/heap_profiling/receiver_pipe_posix.cc @@ -13,12 +13,10 @@ #include "components/services/heap_profiling/public/cpp/sender_pipe.h" #include "components/services/heap_profiling/receiver_pipe.h" #include "components/services/heap_profiling/stream_receiver.h" -#include "mojo/edk/embedder/platform_channel_utils_posix.h" -#include "mojo/edk/embedder/platform_handle.h" namespace heap_profiling { -ReceiverPipe::ReceiverPipe(mojo::edk::ScopedInternalPlatformHandle handle) +ReceiverPipe::ReceiverPipe(mojo::PlatformHandle handle) : ReceiverPipeBase(std::move(handle)), controller_(FROM_HERE), read_buffer_(new char[SenderPipe::kPipeSize]) {} @@ -27,18 +25,16 @@ ReceiverPipe::~ReceiverPipe() {} void ReceiverPipe::StartReadingOnIOThread() { base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor( - handle_.get().handle, true, base::MessagePumpForIO::WATCH_READ, + handle_.GetFD().get(), true, base::MessagePumpForIO::WATCH_READ, &controller_, this); - OnFileCanReadWithoutBlocking(handle_.get().handle); + OnFileCanReadWithoutBlocking(handle_.GetFD().get()); } void ReceiverPipe::OnFileCanReadWithoutBlocking(int fd) { ssize_t bytes_read = 0; do { - base::circular_deque<mojo::edk::InternalPlatformHandle> dummy_for_receive; - bytes_read = HANDLE_EINTR( - read(handle_.get().handle, read_buffer_.get(), SenderPipe::kPipeSize)); + read(handle_.GetFD().get(), read_buffer_.get(), SenderPipe::kPipeSize)); if (bytes_read > 0) { receiver_task_runner_->PostTask( FROM_HERE, diff --git a/chromium/components/services/heap_profiling/receiver_pipe_posix.h b/chromium/components/services/heap_profiling/receiver_pipe_posix.h index f5eb08f9db2..30f0a2fde69 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe_posix.h +++ b/chromium/components/services/heap_profiling/receiver_pipe_posix.h @@ -18,7 +18,7 @@ namespace heap_profiling { class ReceiverPipe : public ReceiverPipeBase, public base::MessagePumpForIO::FdWatcher { public: - explicit ReceiverPipe(mojo::edk::ScopedInternalPlatformHandle handle); + explicit ReceiverPipe(mojo::PlatformHandle handle); // Must be called on the IO thread. void StartReadingOnIOThread(); diff --git a/chromium/components/services/heap_profiling/receiver_pipe_win.cc b/chromium/components/services/heap_profiling/receiver_pipe_win.cc index 8f14087d565..cba6a69c6f9 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe_win.cc +++ b/chromium/components/services/heap_profiling/receiver_pipe_win.cc @@ -16,12 +16,12 @@ namespace heap_profiling { -ReceiverPipe::ReceiverPipe(mojo::edk::ScopedInternalPlatformHandle handle) +ReceiverPipe::ReceiverPipe(mojo::PlatformHandle handle) : ReceiverPipeBase(std::move(handle)), read_buffer_(new char[SenderPipe::kPipeSize]) { ZeroOverlapped(); - base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.get().handle, - this); + base::MessageLoopCurrentForIO::Get()->RegisterIOHandler( + handle_.GetHandle().Get(), this); } ReceiverPipe::~ReceiverPipe() {} @@ -41,7 +41,7 @@ void ReceiverPipe::ReadUntilBlocking() { DCHECK(!read_outstanding_); read_outstanding_ = this; - if (!::ReadFile(handle_.get().handle, read_buffer_.get(), + if (!::ReadFile(handle_.GetHandle().Get(), read_buffer_.get(), SenderPipe::kPipeSize, &bytes_read, &context_.overlapped)) { if (GetLastError() == ERROR_IO_PENDING) { return; diff --git a/chromium/components/services/heap_profiling/receiver_pipe_win.h b/chromium/components/services/heap_profiling/receiver_pipe_win.h index cd6adfb3fbd..603f6036b0c 100644 --- a/chromium/components/services/heap_profiling/receiver_pipe_win.h +++ b/chromium/components/services/heap_profiling/receiver_pipe_win.h @@ -21,7 +21,7 @@ namespace heap_profiling { class ReceiverPipe : public ReceiverPipeBase, public base::MessagePumpForIO::IOHandler { public: - explicit ReceiverPipe(mojo::edk::ScopedInternalPlatformHandle handle); + explicit ReceiverPipe(mojo::PlatformHandle handle); // Must be called on the IO thread. void StartReadingOnIOThread(); diff --git a/chromium/components/services/leveldb/OWNERS b/chromium/components/services/leveldb/OWNERS index e03714b5bc1..be35d981929 100644 --- a/chromium/components/services/leveldb/OWNERS +++ b/chromium/components/services/leveldb/OWNERS @@ -1,4 +1,3 @@ -erg@chromium.org mek@chromium.org per-file manifest.json=set noparent diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_service.cc b/chromium/components/services/pdf_compositor/pdf_compositor_service.cc index e71b72ab482..3cd761e3ddc 100644 --- a/chromium/components/services/pdf_compositor/pdf_compositor_service.cc +++ b/chromium/components/services/pdf_compositor/pdf_compositor_service.cc @@ -25,7 +25,7 @@ #include "content/public/child/dwrite_font_proxy_init_win.h" #elif defined(OS_MACOSX) #include "third_party/blink/public/platform/platform.h" -#include "third_party/skia/include/ports/SkFontMgr.h" +#include "third_party/skia/include/core/SkFontMgr.h" #elif defined(OS_POSIX) && !defined(OS_ANDROID) #include "third_party/blink/public/platform/platform.h" #endif @@ -66,7 +66,7 @@ std::unique_ptr<service_manager::Service> PdfCompositorService::Create( void PdfCompositorService::PrepareToStart() { // Set up discardable memory manager. discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (features::IsMashEnabled()) { + if (!features::IsAshInBrowserProcess()) { #if defined(USE_AURA) context()->connector()->BindInterface(ui::mojom::kServiceName, &manager_ptr); diff --git a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc b/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc index 0af223b62b1..763208cf73d 100644 --- a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc +++ b/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc @@ -14,7 +14,7 @@ namespace printing { std::unique_ptr<service_manager::Service> CreatePdfCompositorService( const std::string& creator) { -#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) +#if defined(OS_POSIX) && !defined(OS_ANDROID) content::UtilityThread::Get()->EnsureBlinkInitializedWithSandboxSupport(); #else content::UtilityThread::Get()->EnsureBlinkInitialized(); |