0

Move Blink Sandbox IPC to Mojo Calls

This is a reland of
https://chromium-review.googlesource.com/c/chromium/src/+/1109964
Tbr'ing previous reviewers from that CL as the exact change has been
previously reviewed there.

The revert was done manually in response to flakiness of viz_browser
tests in MSAN. See issue https://crbug.com/860349 - my analysis is in
issue https://crbug.com/860445 where I disable this test. In short, I
believe my CL exposed a previously existing race condition in that test.

Instead of Chromium IPC macro-defined messages or Mojo, Chrome on Linux
uses hand-pickled IPC messages through a special purpose file descriptor
to send messages from the renderer to the browser host in order to
access FontConfig for font matching and font fallback. This system is
described in docs/linux_sandbox_ipc.md.

For the "Font Matching by Full Font Name / PS Name" effort, see issue
828317, additional out of process font methods are needed. Instead of
adding them to this legacy hand-written IPC, we modernize the Linux
Sandbox IPC mechanism and upgrade it to using Mojo interface definitions
and a service architecture, in which a font service running in an
unsandboxed utility process answers FontConfig requests from the
renderer.

Previous CLs [1], [2] prepared the Font Service to have testing and
additional font fallback and render-style-for-strike methods. Now we can
move Blink over to using this Mojo interface and remove the traditional
sandbox IPC handlers since we do not use the file descriptor based IPC
anymore for FontConfig acces.

For more details, please refer to the design doc in issue 839344.

[1] https://chromium-review.googlesource.com/c/chromium/src/+/1091754
[2] https://chromium-review.googlesource.com/c/chromium/src/+/1087951

Bug: 855021
Change-Id: I74663c5685a7797089e4d69354453146c245e20a
Tbr: skyostil@chromium.org, michaelpg@chromium.org, rsesek@chromium.org, halliwell@chromium.org, thestig@chromium.org, piman@chromium.org, eae@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/1127028
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Cr-Commit-Position: refs/heads/master@{#572930}
This commit is contained in:
Dominik Röttsches
2018-07-06 09:52:40 +00:00
committed by Commit Bot
parent 48898fe7be
commit ac24004e38
60 changed files with 378 additions and 1169 deletions
chrome
chromecast/browser
components/services/font/public/cpp
content
docs
extensions/shell
headless
services/service_manager/sandbox/linux
third_party/blink/public
tools/metrics/histograms

@ -3184,6 +3184,11 @@ are declared in build/common.gypi.
<message name="IDS_UTILITY_PROCESS_FILE_UTILITY_NAME" desc="The name of the utility process used for various Chrome specific file operations.">
Chrome File Utilities
</message>
<if expr="is_linux">
<message name="IDS_UTILITY_PROCESS_FONT_SERVICE_UTILITY_NAME" desc="The name of the utility process used for FontConfig operations for Chrome on Linux.">
Linux Font Service
</message>
</if>
<if expr="not is_android">
<message name="IDS_UTILITY_PROCESS_PROFILE_IMPORTER_NAME" desc="The name of the utility process used for importing profiles.">
Profile Importer

@ -497,6 +497,10 @@
#include "chrome/browser/offline_pages/offline_page_url_loader_request_interceptor.h"
#endif
#if defined(OS_LINUX)
#include "components/services/font/public/interfaces/constants.mojom.h"
#endif
using base::FileDescriptor;
using content::BrowserThread;
using content::BrowserURLHandler;
@ -3638,6 +3642,12 @@ void ChromeContentBrowserClient::RegisterOutOfProcessServices(
&l10n_util::GetStringUTF16, IDS_UTILITY_PROCESS_FILE_UTILITY_NAME);
#endif
#if defined(OS_LINUX)
(*services)[font_service::mojom::kServiceName] =
base::BindRepeating(&l10n_util::GetStringUTF16,
IDS_UTILITY_PROCESS_FONT_SERVICE_UTILITY_NAME);
#endif
(*services)[patch::mojom::kServiceName] = base::BindRepeating(
&l10n_util::GetStringUTF16, IDS_UTILITY_PROCESS_PATCH_NAME);

@ -13,12 +13,38 @@
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_structs.h"
#if defined(OS_LINUX) || defined(OS_OPENBSD)
#include "content/public/child/child_process_sandbox_support_linux.h"
#include "content/public/common/common_sandbox_support_linux.h"
#elif defined(OS_WIN)
#include "third_party/skia/include/core/SkFontMgr.h"
#if !defined(OS_WIN)
namespace {
SkFontStyle::Weight PepperWeightToSkWeight(int pepper_weight) {
switch (pepper_weight) {
case PP_BROWSERFONT_TRUSTED_WEIGHT_100:
return SkFontStyle::kThin_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_200:
return SkFontStyle::kExtraLight_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_300:
return SkFontStyle::kLight_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_400:
return SkFontStyle::kNormal_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_500:
return SkFontStyle::kMedium_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_600:
return SkFontStyle::kSemiBold_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_700:
return SkFontStyle::kBold_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_800:
return SkFontStyle::kExtraBold_Weight;
case PP_BROWSERFONT_TRUSTED_WEIGHT_900:
return SkFontStyle::kBlack_Weight;
default:
NOTREACHED();
return SkFontStyle::kInvisible_Weight;
}
}
} // namespace
#endif
PepperFlashFontFileHost::PepperFlashFontFileHost(
@ -28,24 +54,23 @@ PepperFlashFontFileHost::PepperFlashFontFileHost(
const ppapi::proxy::SerializedFontDescription& description,
PP_PrivateFontCharset charset)
: ResourceHost(host->GetPpapiHost(), instance, resource) {
#if defined(OS_LINUX) || defined(OS_OPENBSD)
fd_.reset(content::MatchFontWithFallback(
description.face,
description.weight >= PP_BROWSERFONT_TRUSTED_WEIGHT_BOLD,
description.italic,
charset,
PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
#elif defined(OS_WIN)
int weight = description.weight;
int weight;
#if defined(OS_WIN)
// TODO(https://crbug.com/857388): Figure out why this diverges from the
// #else block.
weight = description.weight;
if (weight == FW_DONTCARE)
weight = SkFontStyle::kNormal_Weight;
#else
weight = PepperWeightToSkWeight(description.weight);
#endif
SkFontStyle style(weight, SkFontStyle::kNormal_Width,
description.italic ? SkFontStyle::kItalic_Slant
: SkFontStyle::kUpright_Slant);
sk_sp<SkFontMgr> font_mgr(SkFontMgr::RefDefault());
typeface_ = sk_sp<SkTypeface>(
font_mgr->matchFamilyStyle(description.face.c_str(), style));
#endif // defined(OS_LINUX) || defined(OS_OPENBSD)
}
PepperFlashFontFileHost::~PepperFlashFontFileHost() {}
@ -64,12 +89,6 @@ bool PepperFlashFontFileHost::GetFontData(uint32_t table,
void* buffer,
size_t* length) {
bool result = false;
#if defined(OS_LINUX) || defined(OS_OPENBSD)
int fd = fd_.get();
if (fd != -1)
result = content::GetFontTable(fd, table, 0 /* offset */,
reinterpret_cast<uint8_t*>(buffer), length);
#elif defined(OS_WIN)
if (typeface_) {
table = base::ByteSwap(table);
if (buffer == NULL) {
@ -82,7 +101,6 @@ bool PepperFlashFontFileHost::GetFontData(uint32_t table,
result = true;
}
}
#endif
return result;
}

@ -14,12 +14,8 @@
#include "ppapi/c/private/pp_private_font_charset.h"
#include "ppapi/host/resource_host.h"
#if defined(OS_LINUX) || defined(OS_OPENBSD)
#include "base/files/scoped_file.h"
#elif defined(OS_WIN)
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkTypeface.h"
#endif
namespace content {
class RendererPpapiHost;
@ -50,11 +46,7 @@ class PepperFlashFontFileHost : public ppapi::host::ResourceHost {
uint32_t table);
bool GetFontData(uint32_t table, void* buffer, size_t* length);
#if defined(OS_LINUX) || defined(OS_OPENBSD)
base::ScopedFD fd_;
#elif defined(OS_WIN)
sk_sp<SkTypeface> typeface_;
#endif
DISALLOW_COPY_AND_ASSIGN(PepperFlashFontFileHost);
};

@ -199,6 +199,10 @@ static_library("utility") {
if (is_android || enable_extensions) {
deps += [ "//chrome/services/media_gallery_util:lib" ]
}
if (is_linux && !is_android) {
deps += [ "//components/services/font:lib" ]
}
}
if (!is_android) {

@ -201,6 +201,7 @@ cast_source_set("browser") {
deps += [
"//components/metrics:serialization",
"//components/services/font:lib",
"//third_party/fontconfig",
]
}

@ -16,6 +16,7 @@ include_rules = [
"+components/prefs",
"+components/pref_registry",
"+components/proxy_config",
"+components/services/font",
"+components/storage_monitor",
"+components/user_prefs",
"+components/version_info",

@ -76,6 +76,11 @@
#include "media/mojo/services/media_service.h" // nogncheck
#endif // ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS
#if defined(OS_LINUX)
#include "components/services/font/font_service_app.h" // nogncheck
#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
#if defined(OS_LINUX) || defined(OS_ANDROID)
#include "components/crash/content/app/breakpad_linux.h"
#include "components/crash/content/browser/crash_handler_host_linux.h"
@ -683,6 +688,14 @@ void CastContentBrowserClient::RegisterInProcessServices(
#endif
}
void CastContentBrowserClient::RegisterOutOfProcessServices(
OutOfProcessServiceMap* services) {
#if defined(OS_LINUX)
(*services)[font_service::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Font Service");
#endif
}
std::unique_ptr<base::Value>
CastContentBrowserClient::GetServiceManifestOverlay(
base::StringPiece service_name) {

@ -183,6 +183,7 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
void RegisterInProcessServices(
StaticServiceMap* services,
content::ServiceManagerConnection* connection) override;
void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override;
std::unique_ptr<base::Value> GetServiceManifestOverlay(
base::StringPiece service_name) override;
void GetAdditionalMappedFilesForChildProcess(

@ -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();
}
@ -31,7 +32,7 @@ bool FontServiceThread::MatchFamilyName(
SkFontConfigInterface::FontIdentity* out_font_identity,
SkString* out_family_name,
SkFontStyle* out_style) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId());
bool out_valid = false;
// This proxies to the other thread, which proxies to mojo. Only on the reply
@ -54,6 +55,7 @@ bool FontServiceThread::FallbackFontForCharacter(
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(
@ -74,6 +76,7 @@ bool FontServiceThread::FontRenderStyleForStrike(
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(
@ -92,6 +95,7 @@ void FontServiceThread::MatchFontWithFallback(
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,
@ -103,7 +107,7 @@ void FontServiceThread::MatchFontWithFallback(
scoped_refptr<MappedFontFile> FontServiceThread::OpenStream(
const SkFontConfigInterface::FontIdentity& identity) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId());
base::File stream_file;
// This proxies to the other thread, which proxies to mojo. Only on the
@ -210,6 +214,7 @@ void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event,
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();

@ -24,6 +24,7 @@ include_rules = [
# settings, packaging details, installation or crash reporting.
"+components/services/filesystem",
"+components/services/font",
"+crypto",
"+grit/blink_resources.h",

@ -97,13 +97,11 @@
#if defined(OS_LINUX)
#include "base/native_library.h"
#include "base/rand_util.h"
#include "content/common/font_config_ipc_linux.h"
#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/blink/public/platform/web_font_render_style.h"
#include "third_party/boringssl/src/include/openssl/crypto.h"
#include "third_party/boringssl/src/include/openssl/rand.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "third_party/skia/include/ports/SkFontMgr_android.h"
#include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
@ -389,9 +387,6 @@ void PreSandboxInit() {
#endif
InitializeWebRtcModule();
SkFontConfigInterface::SetGlobal(
sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD()));
// Set the android SkFontMgr for blink. We need to ensure this is done
// before the sandbox is initialized to allow the font manager to access
// font configuration files on disk.

@ -1249,8 +1249,6 @@ jumbo_source_set("browser") {
"renderer_host/event_with_latency_info.h",
"renderer_host/file_utilities_host_impl.cc",
"renderer_host/file_utilities_host_impl.h",
"renderer_host/font_utils_linux.cc",
"renderer_host/font_utils_linux.h",
"renderer_host/frame_connector_delegate.cc",
"renderer_host/frame_connector_delegate.h",
"renderer_host/frame_metadata_util.cc",
@ -2046,6 +2044,9 @@ jumbo_source_set("browser") {
if (use_pangocairo) {
sources += [ "renderer_host/pepper/pepper_truetype_font_list_pango.cc" ]
}
if (is_linux && !is_android) {
deps += [ "//components/services/font:ppapi_fontconfig_matching" ]
}
}
if (enable_library_cdms) {

@ -1,91 +0,0 @@
// Copyright 2017 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 <map>
#include <set>
#include <string>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "content/browser/sandbox_ipc_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "services/service_manager/sandbox/switches.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class LinuxIPCBrowserTest : public ContentBrowserTest,
public SandboxIPCHandler::TestObserver,
public testing::WithParamInterface<std::string> {
public:
LinuxIPCBrowserTest() {
SandboxIPCHandler::SetObserverForTests(this);
}
~LinuxIPCBrowserTest() override {}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
if (GetParam() == "no-zygote") {
command_line->AppendSwitch(service_manager::switches::kNoSandbox);
command_line->AppendSwitch(switches::kNoZygote);
}
}
void OnFontOpen(int id) override {
base::AutoLock lock(lock_);
opened_fonts_.insert(font_names_[id]);
}
void OnGetFallbackFontForChar(UChar32 c, std::string name, int id) override {
base::AutoLock lock(lock_);
fallback_fonts_[c] = name;
font_names_[id] = name;
}
std::string FallbackFontName(UChar32 c) {
base::AutoLock lock(lock_);
return fallback_fonts_[c];
}
std::set<std::string> OpenedFonts() {
base::AutoLock lock(lock_);
return opened_fonts_;
}
// These variables are accessed on the IPC thread and the test thread.
// All accesses on the IPC thread should be before the renderer process
// completes navigation, and all accesses on the test thread should be after.
// However we still need a mutex for the accesses to be sequenced according to
// the C++ memory model.
base::Lock lock_;
std::map<UChar32, std::string> fallback_fonts_;
std::map<int, std::string> font_names_;
std::set<std::string> opened_fonts_;
DISALLOW_COPY_AND_ASSIGN(LinuxIPCBrowserTest);
};
// Tests that Linux IPC font fallback code runs round-trip when Zygote is
// disabled. It doesn't care what font is chosen, just that the IPC messages are
// flowing. This test assumes that U+65E5 (CJK "Sun" character) will trigger the
// font fallback codepath.
IN_PROC_BROWSER_TEST_P(LinuxIPCBrowserTest, FontFallbackIPCWorks) {
GURL test_url = GetTestUrl("font", "font_fallback.html");
EXPECT_TRUE(NavigateToURL(shell(), test_url));
EXPECT_THAT(FallbackFontName(U'\U000065E5'), testing::Ne(""));
EXPECT_THAT(OpenedFonts(),
testing::Contains(FallbackFontName(U'\U000065E5')));
}
INSTANTIATE_TEST_CASE_P(LinuxIPCBrowserTest,
LinuxIPCBrowserTest,
::testing::Values("zygote", "no-zygote"));
} // namespace

@ -1,265 +0,0 @@
// Copyright 2014 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 <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"
// TODO(crbug/685022): Guard the inclusion of ppapi headers with
// BUILDFLAG(ENABLE_PLUGINS).
#include "ppapi/c/private/pp_private_font_charset.h" // nogncheck
#include "ppapi/c/trusted/ppb_browser_font_trusted.h" // nogncheck
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 content {
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",
""};
const size_t filename_len = strlen(reinterpret_cast<char*>(c_filename));
for (unsigned j = 0;; j++) {
if (kSFNTExtensions[j][0] == 0) {
// None of the extensions matched.
break;
}
const size_t ext_len = strlen(kSFNTExtensions[j]);
if (filename_len > ext_len &&
memcmp(c_filename + filename_len - ext_len,
kSFNTExtensions[j],
ext_len) == 0) {
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 content

@ -1,22 +0,0 @@
// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
#define CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
#include <stdint.h>
#include <string>
namespace content {
int MatchFontFaceWithFallback(const std::string& face,
bool is_bold,
bool is_italic,
uint32_t charset,
uint32_t fallback_family);
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_

@ -14,8 +14,10 @@
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/font_utils_linux.h"
#include "build/build_config.h"
#include "components/services/font/ppapi_fontconfig_matching.h"
#include "content/public/common/common_sandbox_support_linux.h"
#include "ppapi/buildflags/buildflags.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
@ -74,12 +76,10 @@ int32_t PepperTrueTypeFontLinux::Initialize(
}
}
fd_.reset(
MatchFontFaceWithFallback(desc->family,
desc->weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
desc->style & PP_TRUETYPEFONTSTYLE_ITALIC,
desc->charset,
PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
fd_.reset(font_service::MatchFontFaceWithFallback(
desc->family, desc->weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
desc->style & PP_TRUETYPEFONTSTYLE_ITALIC, desc->charset,
PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
// TODO(bbudge) Modify content API to return results of font matching and
// fallback, so we can update |desc| to reflect that.
return fd_.is_valid() ? PP_OK : PP_ERROR_FAILED;

@ -21,69 +21,15 @@
#include "base/posix/unix_domain_socket.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/renderer_host/font_utils_linux.h"
#include "content/common/font_config_ipc_linux.h"
#include "content/public/common/content_switches.h"
#include "sandbox/linux/services/libc_interceptor.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_fallback_linux.h"
#include "ui/gfx/font_render_params.h"
namespace content {
namespace {
SandboxIPCHandler::TestObserver* g_test_observer = nullptr;
// Converts gfx::FontRenderParams::Hinting to WebFontRenderStyle::hintStyle.
// Returns an int for serialization, but the underlying Blink type is a char.
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;
}
// Converts gfx::FontRenderParams::SubpixelRendering to
// WebFontRenderStyle::useSubpixelRendering. Returns an int for serialization,
// but the underlying Blink type is a char.
int ConvertSubpixelRendering(
gfx::FontRenderParams::SubpixelRendering rendering) {
switch (rendering) {
case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
return 0;
case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
return 1;
case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
return 1;
case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
return 1;
case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
return 1;
}
NOTREACHED() << "Unexpected subpixel rendering value " << rendering;
return 0;
}
} // namespace
const size_t kMaxSandboxIPCMessagePayloadSize = 64;
// static
void SandboxIPCHandler::SetObserverForTests(
SandboxIPCHandler::TestObserver* observer) {
g_test_observer = observer;
}
SandboxIPCHandler::SandboxIPCHandler(int lifeline_fd, int browser_socket)
: lifeline_fd_(lifeline_fd), browser_socket_(browser_socket) {}
@ -136,17 +82,22 @@ void SandboxIPCHandler::HandleRequestFromChild(int fd) {
// A FontConfigIPC::METHOD_MATCH message could be kMaxFontFamilyLength
// bytes long (this is the largest message type).
// The size limit used to be FontConfigIPC::kMaxFontFamilyLength which was
// 2048, but we do not receive FontConfig IPC here anymore. The only payloads
// here are service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT
// and HandleLocalTime from libc_interceptor for which
// kMaxSandboxIPCMessagePayloadSize set to 64 should be plenty.
// 128 bytes padding are necessary so recvmsg() does not return MSG_TRUNC
// error for a maximum length message.
char buf[FontConfigIPC::kMaxFontFamilyLength + 128];
char buf[kMaxSandboxIPCMessagePayloadSize + 128];
const ssize_t len =
base::UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
if (len == -1) {
// TODO: should send an error reply, or the sender might block forever.
if (errno == EMSGSIZE) {
NOTREACHED()
<< "Sandbox host message is larger than kMaxFontFamilyLength";
NOTREACHED() << "Sandbox host message is larger than "
"kMaxSandboxIPCMessagePayloadSize";
} else {
PLOG(ERROR) << "Recvmsg failed";
NOTREACHED();
@ -168,167 +119,12 @@ void SandboxIPCHandler::HandleRequestFromChild(int fd) {
if (sandbox::HandleInterceptedCall(kind, fd, iter, fds))
return;
if (kind == FontConfigIPC::METHOD_MATCH) {
HandleFontMatchRequest(fd, iter, fds);
} else if (kind == FontConfigIPC::METHOD_OPEN) {
HandleFontOpenRequest(fd, iter, fds);
} else if (kind ==
service_manager::SandboxLinux::METHOD_GET_FALLBACK_FONT_FOR_CHAR) {
HandleGetFallbackFontForChar(fd, iter, fds);
} else if (kind ==
service_manager::SandboxLinux::METHOD_GET_STYLE_FOR_STRIKE) {
HandleGetStyleForStrike(fd, iter, fds);
} else if (kind ==
service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT) {
if (kind ==
service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT) {
HandleMakeSharedMemorySegment(fd, iter, fds);
} else if (kind ==
service_manager::SandboxLinux::METHOD_MATCH_WITH_FALLBACK) {
HandleMatchWithFallback(fd, iter, fds);
}
}
int SandboxIPCHandler::FindOrAddPath(const SkString& path) {
int count = paths_.size();
for (int i = 0; i < count; ++i) {
if (path == paths_[i])
return i;
}
paths_.emplace_back(path);
return count;
}
void SandboxIPCHandler::HandleFontMatchRequest(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
SkFontStyle requested_style;
std::string family;
if (!iter.ReadString(&family) ||
!skia::ReadSkFontStyle(&iter, &requested_style))
return;
SkFontConfigInterface::FontIdentity result_identity;
SkString result_family;
SkFontStyle result_style;
SkFontConfigInterface* fc =
SkFontConfigInterface::GetSingletonDirectInterface();
const bool r =
fc->matchFamilyName(family.c_str(), requested_style, &result_identity,
&result_family, &result_style);
base::Pickle reply;
if (!r) {
reply.WriteBool(false);
} else {
// Stash away the returned path, so we can give it an ID (index)
// which will later be given to us in a request to open the file.
int index = FindOrAddPath(result_identity.fString);
result_identity.fID = static_cast<uint32_t>(index);
reply.WriteBool(true);
skia::WriteSkString(&reply, result_family);
skia::WriteSkFontIdentity(&reply, result_identity);
skia::WriteSkFontStyle(&reply, result_style);
}
SendRendererReply(fds, reply, -1);
}
void SandboxIPCHandler::HandleFontOpenRequest(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
uint32_t index;
if (!iter.ReadUInt32(&index))
return;
if (index >= static_cast<uint32_t>(paths_.size()))
return;
if (g_test_observer) {
g_test_observer->OnFontOpen(index);
}
const int result_fd = open(paths_[index].c_str(), O_RDONLY);
base::Pickle reply;
reply.WriteBool(result_fd != -1);
// The receiver will have its own access to the file, so we will close it
// after this send.
SendRendererReply(fds, reply, result_fd);
if (result_fd >= 0) {
int err = IGNORE_EINTR(close(result_fd));
DCHECK(!err);
}
}
void SandboxIPCHandler::HandleGetFallbackFontForChar(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
// The other side of this call is
// content/common/child_process_sandbox_support_impl_linux.cc
UChar32 c;
if (!iter.ReadInt(&c))
return;
std::string preferred_locale;
if (!iter.ReadString(&preferred_locale))
return;
auto fallback_font = gfx::GetFallbackFontForChar(c, preferred_locale);
int fontconfig_interface_id =
FindOrAddPath(SkString(fallback_font.filename.data()));
if (g_test_observer) {
g_test_observer->OnGetFallbackFontForChar(c, fallback_font.name,
fontconfig_interface_id);
}
base::Pickle reply;
reply.WriteString(fallback_font.name);
reply.WriteString(fallback_font.filename);
reply.WriteInt(fontconfig_interface_id);
reply.WriteInt(fallback_font.ttc_index);
reply.WriteBool(fallback_font.is_bold);
reply.WriteBool(fallback_font.is_italic);
SendRendererReply(fds, reply, -1);
}
void SandboxIPCHandler::HandleGetStyleForStrike(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
std::string family;
bool bold;
bool italic;
uint16_t pixel_size;
float device_scale_factor;
if (!iter.ReadString(&family) || !iter.ReadBool(&bold) ||
!iter.ReadBool(&italic) || !iter.ReadUInt16(&pixel_size) ||
!iter.ReadFloat(&device_scale_factor)) {
return;
}
gfx::FontRenderParamsQuery query;
query.families.push_back(family);
query.pixel_size = pixel_size;
query.style = italic ? gfx::Font::ITALIC : 0;
query.weight = bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL;
query.device_scale_factor = device_scale_factor;
const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, nullptr);
// These are passed as ints since they're interpreted as tri-state chars in
// Blink.
base::Pickle reply;
reply.WriteInt(params.use_bitmaps);
reply.WriteInt(params.autohinter);
reply.WriteInt(params.hinting != gfx::FontRenderParams::HINTING_NONE);
reply.WriteInt(ConvertHinting(params.hinting));
reply.WriteInt(params.antialiasing);
reply.WriteInt(ConvertSubpixelRendering(params.subpixel_rendering));
reply.WriteInt(params.subpixel_positioning);
SendRendererReply(fds, reply, -1);
NOTREACHED();
}
void SandboxIPCHandler::HandleMakeSharedMemorySegment(
@ -350,34 +146,6 @@ void SandboxIPCHandler::HandleMakeSharedMemorySegment(
SendRendererReply(fds, reply, shm_fd);
}
void SandboxIPCHandler::HandleMatchWithFallback(
int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds) {
std::string face;
bool is_bold;
bool is_italic;
uint32_t charset;
uint32_t fallback_family;
if (!iter.ReadString(&face) || face.empty() || !iter.ReadBool(&is_bold) ||
!iter.ReadBool(&is_italic) || !iter.ReadUInt32(&charset) ||
!iter.ReadUInt32(&fallback_family)) {
return;
}
int font_fd = MatchFontFaceWithFallback(face, is_bold, is_italic, charset,
fallback_family);
base::Pickle reply;
SendRendererReply(fds, reply, font_fd);
if (font_fd >= 0) {
if (IGNORE_EINTR(close(font_fd)) < 0)
PLOG(ERROR) << "close";
}
}
void SandboxIPCHandler::SendRendererReply(
const std::vector<base::ScopedFD>& fds,
const base::Pickle& reply,

@ -18,8 +18,6 @@
#include "content/common/content_export.h"
#include "third_party/icu/source/common/unicode/uchar.h"
class SkString;
namespace content {
class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
@ -32,55 +30,19 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
void Run() override;
class TestObserver {
public:
virtual void OnGetFallbackFontForChar(UChar32 c,
std::string name,
int id) = 0;
virtual void OnFontOpen(int id) = 0;
};
CONTENT_EXPORT static void SetObserverForTests(TestObserver* observer);
private:
int FindOrAddPath(const SkString& path);
void HandleRequestFromChild(int fd);
void HandleFontMatchRequest(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleFontOpenRequest(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleGetFallbackFontForChar(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleGetStyleForStrike(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleLocaltime(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleMakeSharedMemorySegment(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void HandleMatchWithFallback(int fd,
base::PickleIterator iter,
const std::vector<base::ScopedFD>& fds);
void SendRendererReply(const std::vector<base::ScopedFD>& fds,
const base::Pickle& reply,
int reply_fd);
const int lifeline_fd_;
const int browser_socket_;
std::vector<SkString> paths_;
DISALLOW_COPY_AND_ASSIGN(SandboxIPCHandler);
};

@ -140,6 +140,13 @@ target(link_target_type, "child") {
]
}
if (is_linux && !is_android) {
deps += [
"//components/services/font:lib",
"//components/services/font/public/cpp",
]
}
if (is_android) {
deps += [ "//third_party/android_tools:cpu_features" ]
}

@ -4,6 +4,7 @@ include_rules = [
"+components/tracing",
"+components/variations/child_process_field_trial_syncer.h",
"+components/webcrypto",
"+components/services/font",
"+content/app/strings/grit", # For generated headers
"+content/public/child",

@ -15,6 +15,10 @@
#include "base/posix/unix_domain_socket.h"
#include "base/sys_byteorder.h"
#include "base/trace_event/trace_event.h"
#include "components/services/font/public/cpp/font_loader.h"
#include "components/services/font/public/interfaces/constants.mojom.h"
#include "components/services/font/public/interfaces/font_service.mojom.h"
#include "content/public/common/common_sandbox_support_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/blink/public/platform/linux/web_fallback_font.h"
@ -24,111 +28,64 @@
namespace content {
void GetFallbackFontForCharacter(int32_t character,
void GetFallbackFontForCharacter(sk_sp<font_service::FontLoader> font_loader,
int32_t character,
const char* preferred_locale,
blink::WebFallbackFont* fallbackFont) {
TRACE_EVENT0("sandbox_ipc", "GetFontFamilyForCharacter");
base::Pickle request;
request.WriteInt(
service_manager::SandboxLinux::METHOD_GET_FALLBACK_FONT_FOR_CHAR);
request.WriteInt(character);
request.WriteString(preferred_locale);
uint8_t buf[512];
const ssize_t n = base::UnixDomainSocket::SendRecvMsg(
service_manager::GetSandboxFD(), buf, sizeof(buf), nullptr, request);
blink::WebFallbackFont* fallback_font) {
DCHECK(font_loader.get());
font_service::mojom::FontIdentityPtr font_identity;
bool is_bold = false;
bool is_italic = false;
std::string family_name;
std::string filename;
int fontconfigInterfaceId = 0;
int ttcIndex = 0;
bool isBold = false;
bool isItalic = false;
if (n != -1) {
base::Pickle reply(reinterpret_cast<char*>(buf), n);
base::PickleIterator pickle_iter(reply);
if (pickle_iter.ReadString(&family_name) &&
pickle_iter.ReadString(&filename) &&
pickle_iter.ReadInt(&fontconfigInterfaceId) &&
pickle_iter.ReadInt(&ttcIndex) && pickle_iter.ReadBool(&isBold) &&
pickle_iter.ReadBool(&isItalic)) {
fallbackFont->name = blink::WebString::FromUTF8(family_name);
fallbackFont->filename = blink::WebVector<char>(filename);
fallbackFont->fontconfig_interface_id = fontconfigInterfaceId;
fallbackFont->ttc_index = ttcIndex;
fallbackFont->is_bold = isBold;
fallbackFont->is_italic = isItalic;
}
if (!font_loader->FallbackFontForCharacter(character, preferred_locale,
&font_identity, &family_name,
&is_bold, &is_italic)) {
LOG(ERROR) << "FontService fallback request does not receive a response.";
return;
}
// TODO(drott): Perhaps take WebFallbackFont out of the picture here and pass
// mojo FontIdentityPtr directly?
fallback_font->name =
blink::WebString::FromUTF8(family_name.c_str(), family_name.length());
fallback_font->fontconfig_interface_id = font_identity->id;
fallback_font->filename.Assign(font_identity->str_representation.c_str(),
font_identity->str_representation.length());
fallback_font->ttc_index = font_identity->ttc_index;
fallback_font->is_bold = is_bold;
fallback_font->is_italic = is_italic;
return;
}
void GetRenderStyleForStrike(const char* family,
void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
const char* family,
int size,
bool is_bold,
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
TRACE_EVENT0("sandbox_ipc", "GetRenderStyleForStrike");
DCHECK(font_loader.get());
font_service::mojom::FontIdentityPtr font_identity;
*out = blink::WebFontRenderStyle();
if (size < 0 || size > std::numeric_limits<uint16_t>::max())
return;
base::Pickle request;
request.WriteInt(service_manager::SandboxLinux::METHOD_GET_STYLE_FOR_STRIKE);
request.WriteString(family);
request.WriteBool(is_bold);
request.WriteBool(is_italic);
request.WriteUInt16(size);
request.WriteFloat(device_scale_factor);
font_service::mojom::FontRenderStylePtr font_render_style;
font_loader->FontRenderStyleForStrike(family, size, is_bold, is_italic,
device_scale_factor,
&font_render_style);
uint8_t buf[512];
const ssize_t n = base::UnixDomainSocket::SendRecvMsg(
service_manager::GetSandboxFD(), buf, sizeof(buf), nullptr, request);
if (n == -1)
return;
base::Pickle reply(reinterpret_cast<char*>(buf), n);
base::PickleIterator pickle_iter(reply);
int use_bitmaps, use_autohint, use_hinting, hint_style, use_antialias;
int use_subpixel_rendering, use_subpixel_positioning;
if (pickle_iter.ReadInt(&use_bitmaps) && pickle_iter.ReadInt(&use_autohint) &&
pickle_iter.ReadInt(&use_hinting) && pickle_iter.ReadInt(&hint_style) &&
pickle_iter.ReadInt(&use_antialias) &&
pickle_iter.ReadInt(&use_subpixel_rendering) &&
pickle_iter.ReadInt(&use_subpixel_positioning)) {
out->use_bitmaps = use_bitmaps;
out->use_auto_hint = use_autohint;
out->use_hinting = use_hinting;
out->hint_style = hint_style;
out->use_anti_alias = use_antialias;
out->use_subpixel_rendering = use_subpixel_rendering;
out->use_subpixel_positioning = use_subpixel_positioning;
}
}
int MatchFontWithFallback(const std::string& face,
bool bold,
bool italic,
int charset,
PP_BrowserFont_Trusted_Family fallback_family) {
TRACE_EVENT0("sandbox_ipc", "MatchFontWithFallback");
base::Pickle request;
request.WriteInt(service_manager::SandboxLinux::METHOD_MATCH_WITH_FALLBACK);
request.WriteString(face);
request.WriteBool(bold);
request.WriteBool(italic);
request.WriteUInt32(charset);
request.WriteUInt32(fallback_family);
uint8_t reply_buf[64];
int fd = -1;
base::UnixDomainSocket::SendRecvMsg(service_manager::GetSandboxFD(),
reply_buf, sizeof(reply_buf), &fd,
request);
return fd;
out->use_bitmaps = static_cast<char>(font_render_style->use_bitmaps);
out->use_auto_hint = static_cast<char>(font_render_style->use_autohint);
out->use_hinting = static_cast<char>(font_render_style->use_hinting);
out->hint_style = font_render_style->hint_style;
out->use_anti_alias = static_cast<char>(font_render_style->use_antialias);
out->use_subpixel_rendering =
static_cast<char>(font_render_style->use_subpixel_rendering);
out->use_subpixel_positioning =
static_cast<char>(font_render_style->use_subpixel_positioning);
}
} // namespace content

@ -7,7 +7,8 @@
#include <stdint.h>
#include "content/public/child/child_process_sandbox_support_linux.h"
#include "components/services/font/public/cpp/font_loader.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
struct WebFallbackFont;
@ -20,7 +21,8 @@ namespace content {
// specified by |character|, a UTF-32 character. |preferred_locale| contains the
// preferred locale identifier for |character|. The instance has an empty font
// name if the request could not be satisfied.
void GetFallbackFontForCharacter(const int32_t character,
void GetFallbackFontForCharacter(sk_sp<font_service::FontLoader> font_loader,
const int32_t character,
const char* preferred_locale,
blink::WebFallbackFont* family);
@ -28,7 +30,8 @@ void GetFallbackFontForCharacter(const int32_t character,
// |size_and_style| stores the bold setting in its least-significant bit, the
// italic setting in its second-least-significant bit, and holds the requested
// size in pixels into its remaining bits.
void GetRenderStyleForStrike(const char* family,
void GetRenderStyleForStrike(sk_sp<font_service::FontLoader> font_loader,
const char* family,
int size,
bool is_bold,
bool is_italic,

@ -116,8 +116,6 @@ source_set("common") {
"fileapi/file_system_messages.h",
"fileapi/webblob_messages.h",
"font_cache_dispatcher_win.cc",
"font_config_ipc_linux.cc",
"font_config_ipc_linux.h",
"font_list.cc",
"font_list.h",
"font_list_android.cc",

@ -15,6 +15,9 @@
namespace content {
// TODO(drott): This should be removed once we don't need to support PPAPI
// TrueType functionality anymore, and before that, it should be replaced with
// using FreeType for the purpose instead of reimplementing table parsing.
bool GetFontTable(int fd,
uint32_t table_tag,
off_t offset,

@ -1,179 +0,0 @@
// Copyright (c) 2012 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 "content/common/font_config_ipc_linux.h"
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include <functional>
#include <memory>
#include <utility>
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/ref_counted.h"
#include "base/pickle.h"
#include "base/posix/unix_domain_socket.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
namespace content {
std::size_t SkFontConfigInterfaceFontIdentityHash::operator()(
const SkFontConfigInterface::FontIdentity& sp) const {
std::hash<std::string> stringhash;
std::hash<int> inthash;
size_t r = inthash(sp.fID);
r = r * 41 + inthash(sp.fTTCIndex);
r = r * 41 + stringhash(sp.fString.c_str());
r = r * 41 + inthash(sp.fStyle.weight());
r = r * 41 + inthash(sp.fStyle.slant());
r = r * 41 + inthash(sp.fStyle.width());
return r;
}
// Wikpedia's main country selection page activates 21 fallback fonts,
// doubling this we should be on the generous side as an upper bound,
// but nevertheless not have the mapped typefaces cache grow excessively.
const size_t kMaxMappedTypefaces = 42;
void CloseFD(int fd) {
int err = IGNORE_EINTR(close(fd));
DCHECK(!err);
}
FontConfigIPC::FontConfigIPC(int fd)
: fd_(fd)
, mapped_typefaces_(kMaxMappedTypefaces) {
}
FontConfigIPC::~FontConfigIPC() {
CloseFD(fd_);
}
bool FontConfigIPC::matchFamilyName(const char familyName[],
SkFontStyle requestedStyle,
FontIdentity* outFontIdentity,
SkString* outFamilyName,
SkFontStyle* outStyle) {
TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::matchFamilyName");
size_t familyNameLen = familyName ? strlen(familyName) : 0;
if (familyNameLen > kMaxFontFamilyLength)
return false;
base::Pickle request;
request.WriteInt(METHOD_MATCH);
request.WriteData(familyName, familyNameLen);
skia::WriteSkFontStyle(&request, requestedStyle);
uint8_t reply_buf[2048];
const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
fd_, reply_buf, sizeof(reply_buf), nullptr, request);
if (r == -1)
return false;
base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
base::PickleIterator iter(reply);
bool result;
if (!iter.ReadBool(&result))
return false;
if (!result)
return false;
SkString reply_family;
FontIdentity reply_identity;
SkFontStyle reply_style;
if (!skia::ReadSkString(&iter, &reply_family) ||
!skia::ReadSkFontIdentity(&iter, &reply_identity) ||
!skia::ReadSkFontStyle(&iter, &reply_style)) {
return false;
}
if (outFontIdentity)
*outFontIdentity = reply_identity;
if (outFamilyName)
*outFamilyName = reply_family;
if (outStyle)
*outStyle = reply_style;
return true;
}
static void DestroyMemoryMappedFile(const void*, void* context) {
base::ThreadRestrictions::ScopedAllowIO allow_munmap;
delete static_cast<base::MemoryMappedFile*>(context);
}
SkMemoryStream* FontConfigIPC::mapFileDescriptorToStream(int fd) {
std::unique_ptr<base::MemoryMappedFile> mapped_font_file(
new base::MemoryMappedFile);
base::ThreadRestrictions::ScopedAllowIO allow_mmap;
mapped_font_file->Initialize(base::File(fd));
DCHECK(mapped_font_file->IsValid());
sk_sp<SkData> data =
SkData::MakeWithProc(mapped_font_file->data(), mapped_font_file->length(),
&DestroyMemoryMappedFile, mapped_font_file.get());
if (!data)
return nullptr;
ignore_result(mapped_font_file.release()); // Ownership transferred to SkDataB
return new SkMemoryStream(std::move(data));
}
SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) {
TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream");
base::Pickle request;
request.WriteInt(METHOD_OPEN);
request.WriteUInt32(identity.fID);
int result_fd = -1;
uint8_t reply_buf[256];
const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
fd_, reply_buf, sizeof(reply_buf), &result_fd, request);
if (r == -1)
return nullptr;
base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
bool result;
base::PickleIterator iter(reply);
if (!iter.ReadBool(&result) || !result) {
if (result_fd)
CloseFD(result_fd);
return nullptr;
}
return mapFileDescriptorToStream(result_fd);
}
sk_sp<SkTypeface> FontConfigIPC::makeTypeface(
const SkFontConfigInterface::FontIdentity& identity) {
base::AutoLock lock(lock_);
auto mapped_typefaces_it = mapped_typefaces_.Get(identity);
if (mapped_typefaces_it != mapped_typefaces_.end())
return mapped_typefaces_it->second;
SkStreamAsset* typeface_stream = openStream(identity);
if (!typeface_stream)
return nullptr;
sk_sp<SkTypeface> typeface_from_stream(
SkTypeface::MakeFromStream(typeface_stream, identity.fTTCIndex));
auto mapped_typefaces_insert_it =
mapped_typefaces_.Put(identity, std::move(typeface_from_stream));
return mapped_typefaces_insert_it->second;
}
} // namespace content

@ -1,81 +0,0 @@
// Copyright (c) 2012 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 CONTENT_COMMON_FONT_CONFIG_IPC_LINUX_H_
#define CONTENT_COMMON_FONT_CONFIG_IPC_LINUX_H_
#include "base/compiler_specific.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include <stddef.h>
#include <string>
class SkString;
namespace content {
struct SkFontConfigInterfaceFontIdentityHash {
std::size_t operator()(const SkFontConfigInterface::FontIdentity& sp) const;
};
// FontConfig implementation for Skia that proxies out of process to get out
// of the sandbox. See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
class FontConfigIPC : public SkFontConfigInterface {
public:
explicit FontConfigIPC(int fd);
~FontConfigIPC() override;
bool matchFamilyName(const char familyName[],
SkFontStyle requested,
FontIdentity* outFontIdentifier,
SkString* outFamilyName,
SkFontStyle* outStyle) override;
sk_sp<SkTypeface> makeTypeface(const FontIdentity& identity) override
WARN_UNUSED_RESULT;
enum Method {
METHOD_MATCH = 0,
METHOD_OPEN = 1,
};
enum {
kMaxFontFamilyLength = 2048
};
private:
// Marking this private in Blink's implementation of SkFontConfigInterface
// since our caching implementation's efficacy is impaired if both
// createTypeface and openStream are used in parallel.
SkStreamAsset* openStream(const FontIdentity&) override;
SkMemoryStream* mapFileDescriptorToStream(int fd);
const int fd_;
// Lock preventing multiple threads from creating a typeface and removing
// an element from |mapped_typefaces_| map at the same time.
base::Lock lock_;
// Practically, this hash_map definition means that we re-map the same font
// file multiple times if we receive createTypeface requests for multiple
// ttc-indices or styles but the same fontconfig interface id. Since the usage
// frequency of ttc indices is very low, and style is not used by clients of
// this API, this seems okay.
base::HashingMRUCache<FontIdentity,
sk_sp<SkTypeface>,
SkFontConfigInterfaceFontIdentityHash>
mapped_typefaces_;
DISALLOW_COPY_AND_ASSIGN(FontConfigIPC);
};
} // namespace content
#endif // CONTENT_COMMON_FONT_CONFIG_IPC_LINUX_H_

@ -51,6 +51,7 @@ source_set("ppapi_plugin_sources") {
deps = [
"//base",
"//components/discardable_memory/client",
"//components/services/font/public/cpp:cpp",
"//content:export",
"//content/child",
"//content/public/child:child_sources",

@ -40,11 +40,15 @@ namespace content {
class PpapiBlinkPlatformImpl::SandboxSupport : public WebSandboxSupport {
public:
#if defined(OS_LINUX)
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
#endif
~SandboxSupport() override {}
#if defined(OS_MACOSX)
bool LoadFont(CTFontRef srcFont, CGFontRef* out, uint32_t* fontID) override;
#elif defined(OS_POSIX)
#elif defined(OS_LINUX)
SandboxSupport();
void GetFallbackFontForCharacter(
WebUChar32 character,
@ -64,6 +68,7 @@ class PpapiBlinkPlatformImpl::SandboxSupport : public WebSandboxSupport {
std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
// For debugging crbug.com/312965
base::PlatformThreadId creation_thread_;
sk_sp<font_service::FontLoader> font_loader_;
#endif
};
@ -105,8 +110,8 @@ void PpapiBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter(
return;
}
content::GetFallbackFontForCharacter(character, preferred_locale,
fallbackFont);
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallbackFont);
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
@ -117,8 +122,8 @@ void PpapiBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike(
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(family, size, is_bold, is_italic, device_scale_factor,
out);
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
#endif
@ -126,8 +131,14 @@ void PpapiBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike(
#endif // !defined(OS_ANDROID) && !defined(OS_WIN)
PpapiBlinkPlatformImpl::PpapiBlinkPlatformImpl() {
#if !defined(OS_ANDROID) && !defined(OS_WIN)
sandbox_support_.reset(new PpapiBlinkPlatformImpl::SandboxSupport);
#if defined(OS_LINUX) && !defined(OS_ANDROID)
font_loader_ =
sk_make_sp<font_service::FontLoader>(ChildThread::Get()->GetConnector());
SkFontConfigInterface::SetGlobal(font_loader_);
sandbox_support_.reset(
new PpapiBlinkPlatformImpl::SandboxSupport(font_loader_));
#elif defined(OS_MACOSX)
sandbox_support_.reset(new PpapiBlinkPlatformImpl::SandboxSupport());
#endif
}

@ -13,6 +13,11 @@
#include "build/build_config.h"
#include "content/child/blink_platform_impl.h"
#if defined(OS_LINUX)
#include "components/services/font/public/cpp/font_loader.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#endif
namespace content {
class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
@ -53,6 +58,10 @@ class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
std::unique_ptr<SandboxSupport> sandbox_support_;
#endif
#if defined(OS_LINUX)
sk_sp<font_service::FontLoader> font_loader_;
#endif
DISALLOW_COPY_AND_ASSIGN(PpapiBlinkPlatformImpl);
};

@ -197,6 +197,10 @@ service_manifest("packaged_services_manifest") {
"//services/video_capture:manifest",
"//services/viz:manifest",
]
if (is_linux && !is_android) {
packaged_services += [ "//components/services/font:manifest" ]
}
}
service_manifest("browser_manifest") {

@ -25,6 +25,7 @@
"plugin"
],
"device": [ "device:power_monitor" ],
"font_service": [ "font_service" ],
"ui": [ "discardable_memory" ]
}
}

@ -33,6 +33,7 @@
"font_loader",
"renderer"
],
"font_service": [ "font_service" ],
"metrics": [ "url_keyed_metrics" ],
"device": [
"device:power_monitor",

@ -29,7 +29,8 @@
"device": [
"device:power_monitor",
"device:time_zone_monitor"
]
],
"font_service": [ "font_service" ]
}
}
},

@ -29,7 +29,6 @@ jumbo_source_set("child_sources") {
visibility = [ "//content/*" ]
sources = [
"child_process_sandbox_support_linux.h",
"child_thread.h",
"dwrite_font_proxy_init_win.h",
"image_decoder_utils.h",

@ -1,33 +0,0 @@
// Copyright 2017 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 CONTENT_PUBLIC_CHILD_CHILD_PROCESS_SANDBOX_SUPPORT_LINUX_H_
#define CONTENT_PUBLIC_CHILD_CHILD_PROCESS_SANDBOX_SUPPORT_LINUX_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "content/common/content_export.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
namespace content {
// Return a read-only file descriptor to the font which best matches the given
// properties or -1 on failure.
// charset: specifies the language(s) that the font must cover. See
// render_sandbox_host_linux.cc for more information.
// fallback_family: If not set to PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT, font
// selection should fall back to generic Windows font names like Arial and
// Times New Roman.
CONTENT_EXPORT int MatchFontWithFallback(
const std::string& face,
bool bold,
bool italic,
int charset,
PP_BrowserFont_Trusted_Family fallback_family);
}; // namespace content
#endif // CONTENT_PUBLIC_CHILD_CHILD_PROCESS_SANDBOX_SUPPORT_LINUX_H_

@ -1024,6 +1024,16 @@ target(link_target_type, "renderer") {
deps += [ "//sandbox:sandbox_buildflags" ]
}
if (is_linux && !is_android) {
deps += [
"//components/services/font:lib",
"//components/services/font/public/cpp",
]
data_deps = [
"//components/services/font:font_service",
]
}
if (use_ozone) {
deps += [ "//ui/ozone" ]
}

@ -18,6 +18,10 @@ static_library("mus") {
configs += [ "//content:content_implementation" ]
public_deps = [
"//content/public/common:common_sources",
]
deps = [
"//base",
"//cc",
@ -25,7 +29,6 @@ static_library("mus") {
"//components/viz/client",
"//content/common",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
"//media/mojo/interfaces:remoting",
"//services/service_manager/public/cpp",
"//services/ui/public/cpp",

@ -205,13 +205,17 @@ gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) {
class RendererBlinkPlatformImpl::SandboxSupport
: public blink::WebSandboxSupport {
public:
#if defined(OS_LINUX)
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
#endif
~SandboxSupport() override {}
#if defined(OS_MACOSX)
bool LoadFont(CTFontRef src_font,
CGFontRef* container,
uint32_t* font_id) override;
#elif defined(OS_POSIX)
#elif defined(OS_LINUX)
void GetFallbackFontForCharacter(
blink::WebUChar32 character,
const char* preferred_locale,
@ -229,6 +233,7 @@ class RendererBlinkPlatformImpl::SandboxSupport
// here.
base::Lock unicode_font_families_mutex_;
std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
sk_sp<font_service::FontLoader> font_loader_;
#endif
};
#endif // !defined(OS_ANDROID) && !defined(OS_WIN)
@ -247,13 +252,6 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
is_locked_to_site_(false),
default_task_runner_(main_thread_scheduler->DefaultTaskRunner()),
main_thread_scheduler_(main_thread_scheduler) {
#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
if (g_sandbox_enabled && sandboxEnabled()) {
sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport);
} else {
DVLOG(1) << "Disabling sandbox support for testing.";
}
#endif
// RenderThread may not exist in some tests.
if (RenderThreadImpl::current()) {
@ -267,11 +265,28 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
web_idb_factory_.reset(new WebIDBFactoryImpl(
sync_message_filter_,
RenderThreadImpl::current()->GetIOTaskRunner().get()));
#if defined(OS_LINUX)
font_loader_ = sk_make_sp<font_service::FontLoader>(connector_.get());
SkFontConfigInterface::SetGlobal(font_loader_);
#endif
} else {
service_manager::mojom::ConnectorRequest request;
connector_ = service_manager::Connector::Create(&request);
}
#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
if (g_sandbox_enabled && sandboxEnabled()) {
#if defined(OS_MACOSX)
sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport());
#else
sandbox_support_.reset(
new RendererBlinkPlatformImpl::SandboxSupport(font_loader_));
#endif
} else {
DVLOG(1) << "Disabling sandbox support for testing.";
}
#endif
blink_interface_provider_.reset(
new BlinkInterfaceProviderImpl(connector_.get()));
top_level_blame_context_.Initialize();
@ -592,8 +607,8 @@ void RendererBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter(
return;
}
content::GetFallbackFontForCharacter(character, preferred_locale,
fallbackFont);
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallbackFont);
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
@ -604,8 +619,8 @@ void RendererBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike(
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(family, size, is_bold, is_italic, device_scale_factor,
out);
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
#endif

@ -29,6 +29,11 @@
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h"
#include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h"
#if defined(OS_LINUX)
#include "components/services/font/public/cpp/font_loader.h" // nogncheck
#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
#endif
namespace IPC {
class SyncMessageFilter;
}
@ -318,6 +323,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::mojom::WebDatabaseHostPtrInfo web_database_host_info_;
scoped_refptr<blink::mojom::ThreadSafeWebDatabaseHostPtr> web_database_host_;
#if defined(OS_LINUX)
sk_sp<font_service::FontLoader> font_loader_;
#endif
THREAD_CHECKER(main_thread_checker_);
DISALLOW_COPY_AND_ASSIGN(RendererBlinkPlatformImpl);

@ -43,14 +43,6 @@
#include "base/android/library_loader/library_loader_hooks.h"
#endif // OS_ANDROID
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(OS_FUCHSIA)
#include "content/common/font_config_ipc_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#endif
#if defined(OS_MACOSX)
#include <Carbon/Carbon.h>
#include <signal.h>
@ -121,16 +113,6 @@ int RendererMain(const MainFunctionParams& parameters) {
}
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
!defined(OS_FUCHSIA)
// This call could already have been made from zygote_main_linux.cc. However
// we need to do it here if Zygote is disabled.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote)) {
SkFontConfigInterface::SetGlobal(
sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD()));
}
#endif
InitializeSkia();
// This function allows pausing execution using the --renderer-startup-dialog

@ -352,6 +352,10 @@ static_library("content_shell_lib") {
]
}
if (is_linux && !is_android) {
deps += [ "//components/services/font:lib" ]
}
if (use_x11) {
# Some tests rely on this tool at runtime. Note: it might be better if
# the tests that needed it had this as a dep instead of adding it here.
@ -892,6 +896,10 @@ mojom("mojo_bindings") {
service_manifest("content_shell_packaged_services_manifest_overlay") {
source = "//content/shell/browser/content_shell_packaged_services_manifest_overlay.json"
packaged_services = [ "//services/test/echo:manifest" ]
if (is_linux && !is_android) {
packaged_services += [ "//components/services/font:manifest" ]
}
}
group("content_shell_crash_test") {

@ -65,6 +65,11 @@
#include "content/public/common/content_descriptors.h"
#endif
#if defined(OS_LINUX)
#include "components/services/font/font_service_app.h" // nogncheck
#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
@ -227,6 +232,10 @@ void ShellContentBrowserClient::RegisterOutOfProcessServices(
base::BindRepeating(&base::ASCIIToUTF16, "Test Service");
(*services)[echo::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Echo Service");
#if defined(OS_LINUX)
(*services)[font_service::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Font Service");
#endif
}
bool ShellContentBrowserClient::ShouldTerminateOnServiceQuit(

@ -1058,10 +1058,7 @@ test("content_browsertests") {
}
if (is_linux) {
sources += [
"../browser/linux_ipc_browsertest.cc",
"../zygote/zygote_browsertest.cc",
]
sources += [ "../zygote/zygote_browsertest.cc" ]
deps += [ "//ui/gfx:test_support" ]
}

@ -68,6 +68,10 @@ jumbo_source_set("utility") {
"//media/mojo/services",
]
}
if (is_linux && !is_android) {
deps += [ "//components/services/font:lib" ]
}
}
# See comment at the top of //content/BUILD.gn for how this works.

@ -13,6 +13,8 @@
#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
#include "base/synchronization/lock.h"
#include "content/child/child_process_sandbox_support_impl_linux.h"
#include "content/child/child_thread_impl.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/platform/linux/web_fallback_font.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#endif
@ -30,6 +32,10 @@ namespace content {
class UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport
: public blink::WebSandboxSupport {
public:
#if defined(OS_LINUX)
explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader)
: font_loader_(std::move(font_loader)) {}
#endif
~SandboxSupport() override {}
#if defined(OS_MACOSX)
@ -53,14 +59,20 @@ class UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport
base::Lock unicode_font_families_mutex_;
// Maps unicode chars to their fallback fonts.
std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
sk_sp<font_service::FontLoader> font_loader_;
#endif // defined(OS_MACOSX)
};
#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
UtilityBlinkPlatformWithSandboxSupportImpl::
UtilityBlinkPlatformWithSandboxSupportImpl() {
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
UtilityBlinkPlatformWithSandboxSupportImpl(
service_manager::Connector* connector) {
#if defined(OS_LINUX)
font_loader_ = sk_make_sp<font_service::FontLoader>(connector);
SkFontConfigInterface::SetGlobal(font_loader_);
sandbox_support_ = std::make_unique<SandboxSupport>(font_loader_);
#elif defined(OS_MACOSX)
sandbox_support_ = std::make_unique<SandboxSupport>();
#endif
}
@ -105,9 +117,8 @@ void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
fallback_font->is_italic = iter->second.is_italic;
return;
}
content::GetFallbackFontForCharacter(character, preferred_locale,
fallback_font);
content::GetFallbackFontForCharacter(font_loader_, character,
preferred_locale, fallback_font);
unicode_font_families_.emplace(character, *fallback_font);
}
@ -118,8 +129,8 @@ void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
bool is_italic,
float device_scale_factor,
blink::WebFontRenderStyle* out) {
GetRenderStyleForStrike(family, size, is_bold, is_italic, device_scale_factor,
out);
GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic,
device_scale_factor, out);
}
#endif

@ -11,10 +11,19 @@
#include "build/build_config.h"
#include "content/utility/utility_blink_platform_impl.h"
#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
#include "components/services/font/public/cpp/font_loader.h" // nogncheck
#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
#endif
namespace blink {
class WebSandboxSupport;
}
namespace service_manager {
class Connector;
}
namespace content {
// This class extends from UtilityBlinkPlatformImpl with added blink web
@ -22,7 +31,9 @@ namespace content {
class UtilityBlinkPlatformWithSandboxSupportImpl
: public UtilityBlinkPlatformImpl {
public:
UtilityBlinkPlatformWithSandboxSupportImpl();
UtilityBlinkPlatformWithSandboxSupportImpl() = delete;
explicit UtilityBlinkPlatformWithSandboxSupportImpl(
service_manager::Connector*);
~UtilityBlinkPlatformWithSandboxSupportImpl() override;
// BlinkPlatformImpl
@ -33,6 +44,9 @@ class UtilityBlinkPlatformWithSandboxSupportImpl
class SandboxSupport;
std::unique_ptr<SandboxSupport> sandbox_support_;
#endif
#if defined(OS_LINUX)
sk_sp<font_service::FontLoader> font_loader_;
#endif
DISALLOW_COPY_AND_ASSIGN(UtilityBlinkPlatformWithSandboxSupportImpl);
};

@ -45,6 +45,11 @@
#endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
#endif
#if defined(OS_LINUX)
#include "components/services/font/font_service_app.h" // nogncheck
#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox.h"
@ -170,6 +175,14 @@ void UtilityServiceFactory::RegisterServices(ServiceMap* services) {
services->insert(
std::make_pair(content::mojom::kNetworkServiceName, network_info));
}
#if defined(OS_LINUX)
service_manager::EmbeddedServiceInfo font_service_info;
font_service_info.factory =
base::BindRepeating(&font_service::FontServiceApp::CreateService);
services->insert(
std::make_pair(font_service::mojom::kServiceName, font_service_info));
#endif
}
void UtilityServiceFactory::OnServiceQuit() {

@ -118,7 +118,8 @@ void UtilityThreadImpl::EnsureBlinkInitializedInternal(bool sandbox_support) {
blink_platform_impl_ =
sandbox_support
? std::make_unique<UtilityBlinkPlatformWithSandboxSupportImpl>()
? std::make_unique<UtilityBlinkPlatformWithSandboxSupportImpl>(
GetConnector())
: std::make_unique<UtilityBlinkPlatformImpl>();
blink::Platform::Initialize(blink_platform_impl_.get());
}

@ -4,11 +4,13 @@ The Sandbox IPC system is separate from the 'main' IPC system. The sandbox IPC
is a lower level system which deals with cases where we need to route requests
from the bottom of the call stack up into the browser.
The motivating example is Skia, which uses fontconfig to load fonts. In a
chrooted renderer we cannot access the user's fontcache, nor the font files
themselves. However, font loading happens when we have called through WebKit,
through Skia and into the SkFontHost. At this point, we cannot loop back around
to use the main IPC system.
The motivating example used to be Skia, which uses fontconfig to load
fonts. Howvever, the OOP IPC for FontConfig was moved to using Font Service and
the `components/services/font/public/cpp/font_loader.h` interface.
These days, only the out-of-process localtime implementation as well as
an OOP call for making a shared memory segment are using the Sandbox IPC
file-descriptor based system. See `sandbox/linux/services/libc_interceptor.cc`.
Thus we define a small IPC system which doesn't depend on anything but `base`
and which can make synchronous requests to the browser process.
@ -36,22 +38,12 @@ requests so that should be a good starting point.
Here is a (possibly incomplete) list of endpoints in the renderer:
### fontconfig
### localtime
As mentioned above, the motivating example of this is dealing with fontconfig
from a chrooted renderer. We implement our own Skia FontHost, outside of the
Skia tree, in `skia/ext/SkFontHost_fontconfig**`.
`content/browser/sandbox_ipc_linux.h` defines HandleLocalTime which is
implemented in `sandbox/linux/services/libc_interceptor.cc`.
There are two methods used. One for performing a match against the fontconfig
data and one to return a file descriptor to a font file resulting from one of
those matches. The only wrinkle is that fontconfig is a single-threaded library
and it's already used in the browser by GTK itself.
### Creating a shared memory segment
Thus, we have a couple of options:
1. Handle the requests on the UI thread in the browser.
1. Handle the requests in a separate address space.
The original implementation did the former (handle on UI thread). This turned
out to be a terrible idea, performance wise, so we now handle the requests on a
dedicated process.
`content/browser/sandbox_ipc_linux.h` defines HandleMakeSharedMemorySegment
which is implemented in `content/browser/sandbox_ipc_linux.cc`.

@ -222,6 +222,10 @@ source_set("app_shell_lib") {
]
}
if (is_linux) {
deps += [ "//components/services/font/public/cpp" ]
}
if (is_chromeos) {
sources += [
"browser/api/vpn_provider/vpn_service_factory.cc",

@ -8,6 +8,7 @@ include_rules = [
"+components/network_session_configurator/common",
"+components/pref_registry",
"+components/sessions",
"+components/services/font",
"+components/update_client",
"+components/user_prefs",
"+components/web_modal",

@ -8,8 +8,10 @@
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "components/guest_view/browser/guest_view_message_filter.h"
#include "components/nacl/common/buildflags.h"
#include "content/public/browser/browser_main_runner.h"
@ -56,6 +58,12 @@
#include "content/public/browser/child_process_data.h"
#endif
#if defined(OS_LINUX)
#include "base/strings/utf_string_conversions.h"
#include "components/services/font/font_service_app.h" // nogncheck
#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
using base::CommandLine;
using content::BrowserContext;
using content::BrowserThread;
@ -257,6 +265,14 @@ ShellContentBrowserClient::CreateThrottlesForNavigation(
return throttles;
}
void ShellContentBrowserClient::RegisterOutOfProcessServices(
OutOfProcessServiceMap* services) {
#if defined(OS_LINUX)
(*services)[font_service::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Font Service");
#endif
}
std::unique_ptr<content::NavigationUIData>
ShellContentBrowserClient::GetNavigationUIData(
content::NavigationHandle* navigation_handle) {

@ -64,6 +64,7 @@ class ShellContentBrowserClient : public content::ContentBrowserClient {
std::vector<std::unique_ptr<content::NavigationThrottle>>
CreateThrottlesForNavigation(
content::NavigationHandle* navigation_handle) override;
void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override;
std::unique_ptr<content::NavigationUIData> GetNavigationUIData(
content::NavigationHandle* navigation_handle) override;
void RegisterNonNetworkNavigationURLLoaderFactories(

@ -449,6 +449,10 @@ component("headless") {
deps += [ "//components/os_crypt" ]
}
if (is_linux) {
deps += [ "//components/services/font/public/cpp" ]
}
if (is_component_build) {
sources += [
"lib/browser/headless_content_browser_client.cc",

@ -3,6 +3,7 @@ include_rules = [
"+components/printing/browser",
"+components/printing/common",
"+components/security_state",
"+components/services/font",
"+components/viz",
"+printing",
"+storage/browser/quota",

@ -13,6 +13,7 @@
#include "base/json/json_reader.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_certificate_delegate.h"
@ -50,6 +51,11 @@
#include "components/services/pdf_compositor/public/interfaces/pdf_compositor.mojom.h"
#endif
#if defined(OS_LINUX)
#include "components/services/font/font_service_app.h" // nogncheck
#include "components/services/font/public/interfaces/constants.mojom.h" // nogncheck
#endif
namespace headless {
namespace {
@ -165,6 +171,10 @@ void HeadlessContentBrowserClient::RegisterOutOfProcessServices(
(*services)[printing::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "PDF Compositor Service");
#endif
#if defined(OS_LINUX)
(*services)[font_service::mojom::kServiceName] =
base::BindRepeating(&base::ASCIIToUTF16, "Font Service");
#endif
}
std::unique_ptr<base::Value>

@ -56,11 +56,11 @@ class SERVICE_MANAGER_SANDBOX_EXPORT SandboxLinux {
// This isn't the full list, values < 32 are reserved for methods called from
// Skia, and values < 64 are reserved for libc_interceptor.cc.
enum LinuxSandboxIPCMethods {
METHOD_GET_FALLBACK_FONT_FOR_CHAR = 64,
DEPRECATED_METHOD_GET_FALLBACK_FONT_FOR_CHAR = 64,
DEPRECATED_METHOD_GET_CHILD_WITH_INODE,
METHOD_GET_STYLE_FOR_STRIKE,
DEPRECATED_METHOD_GET_STYLE_FOR_STRIKE,
METHOD_MAKE_SHARED_MEMORY_SEGMENT,
METHOD_MATCH_WITH_FALLBACK,
DEPRECATED_METHOD_MATCH_WITH_FALLBACK,
};
// These form a bitmask which describes the conditions of the Linux sandbox.

@ -739,6 +739,7 @@ mojom("mojo_bindings") {
":web_client_hints_types_mojo_bindings",
":web_feature_mojo_bindings",
"//components/payments/mojom",
"//components/services/font/public/interfaces",
"//device/bluetooth/public/mojom",
"//mojo/public/mojom/base",
"//services/device/public/mojom",

@ -47584,6 +47584,7 @@ Full version information for the fingerprint enum values:
<int value="-400619253" label="mus_demo"/>
<int value="-254080081" label="cdm"/>
<int value="-2816355" label="profile_import"/>
<int value="69152809" label="font_service"/>
<int value="357224138" label="user_id"/>
<int value="498331100" label="preferences"/>
<int value="573935755" label="removable_storage_writer"/>