Skip to content

Commit

Permalink
re-land 187283 -- switch to skia's version of SkFontHost_fontconfig
Browse files Browse the repository at this point in the history
add suppressions.txt to account for global typeface cache
Review URL: https://codereview.chromium.org/12764009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187572 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
reed@google.com committed Mar 12, 2013
1 parent 0b57b3a commit 9628e0d
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 1,151 deletions.
88 changes: 40 additions & 48 deletions content/browser/renderer_host/render_sandbox_host_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@
#include "content/common/font_config_ipc_linux.h"
#include "content/common/sandbox_linux.h"
#include "content/common/webkitplatformsupport_impl.h"
#include "skia/ext/SkFontHost_fontconfig_direct.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/linux/WebFontInfo.h"
#include "third_party/npapi/bindings/npapi_extensions.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "ui/gfx/font_render_params_linux.h"

using WebKit::WebCString;
Expand All @@ -59,8 +60,7 @@ class SandboxIPCProcess {
SandboxIPCProcess(int lifeline_fd, int browser_socket,
std::string sandbox_cmd)
: lifeline_fd_(lifeline_fd),
browser_socket_(browser_socket),
font_config_(new FontConfigDirect()) {
browser_socket_(browser_socket) {
if (!sandbox_cmd.empty()) {
sandbox_cmd_.push_back(sandbox_cmd);
sandbox_cmd_.push_back(base::kFindInodeSwitch);
Expand Down Expand Up @@ -119,7 +119,7 @@ class SandboxIPCProcess {
// bytes long (this is the largest message type).
// 128 bytes padding are necessary so recvmsg() does not return MSG_TRUNC
// error for a maximum length message.
char buf[FontConfigInterface::kMaxFontFamilyLength + 128];
char buf[FontConfigIPC::kMaxFontFamilyLength + 128];

const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
if (len == -1) {
Expand Down Expand Up @@ -163,64 +163,58 @@ class SandboxIPCProcess {
}
}

void HandleFontMatchRequest(int fd, const Pickle& pickle, PickleIterator iter,
std::vector<int>& fds) {
bool filefaceid_valid;
uint32_t filefaceid = 0;

if (!pickle.ReadBool(&iter, &filefaceid_valid))
return;
if (filefaceid_valid) {
if (!pickle.ReadUInt32(&iter, &filefaceid))
return;
}
bool is_bold, is_italic;
if (!pickle.ReadBool(&iter, &is_bold) ||
!pickle.ReadBool(&iter, &is_italic)) {
return;
}

uint32_t characters_bytes;
if (!pickle.ReadUInt32(&iter, &characters_bytes))
return;
const char* characters = NULL;
if (characters_bytes > 0) {
const uint32_t kMaxCharactersBytes = 1 << 10;
if (characters_bytes % 2 != 0 || // We expect UTF-16.
characters_bytes > kMaxCharactersBytes ||
!pickle.ReadBytes(&iter, &characters, characters_bytes))
return;
int FindOrAddPath(const SkString& path) {
int count = paths_.count();
for (int i = 0; i < count; ++i) {
if (path == *paths_[i])
return i;
}
*paths_.append() = new SkString(path);
return count;
}

void HandleFontMatchRequest(int fd, const Pickle& pickle, PickleIterator iter,
std::vector<int>& fds) {
uint32_t requested_style;
std::string family;
if (!pickle.ReadString(&iter, &family))
if (!pickle.ReadString(&iter, &family) ||
!pickle.ReadUInt32(&iter, &requested_style))
return;

std::string result_family;
unsigned result_filefaceid;
const bool r = font_config_->Match(
&result_family, &result_filefaceid, filefaceid_valid, filefaceid,
family, characters, characters_bytes, &is_bold, &is_italic);
SkFontConfigInterface::FontIdentity result_identity;
SkString result_family;
SkTypeface::Style result_style;
SkFontConfigInterface* fc =
SkFontConfigInterface::GetSingletonDirectInterface();
const bool r = fc->matchFamilyName(
family.c_str(), static_cast<SkTypeface::Style>(requested_style),
&result_identity, &result_family, &result_style);

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);
reply.WriteUInt32(result_filefaceid);
reply.WriteString(result_family);
reply.WriteBool(is_bold);
reply.WriteBool(is_italic);
skia::WriteSkString(&reply, result_family);
skia::WriteSkFontIdentity(&reply, result_identity);
reply.WriteUInt32(result_style);
}
SendRendererReply(fds, reply, -1);
}

void HandleFontOpenRequest(int fd, const Pickle& pickle, PickleIterator iter,
std::vector<int>& fds) {
uint32_t filefaceid;
if (!pickle.ReadUInt32(&iter, &filefaceid))
uint32_t index;
if (!pickle.ReadUInt32(&iter, &index))
return;
const int result_fd = font_config_->Open(filefaceid);
if (index >= static_cast<uint32_t>(paths_.count()))
return;
const int result_fd = open(paths_[index]->c_str(), O_RDONLY);

Pickle reply;
if (result_fd == -1) {
Expand All @@ -230,9 +224,6 @@ class SandboxIPCProcess {
}

SendRendererReply(fds, reply, result_fd);

if (result_fd >= 0)
close(result_fd);
}

void HandleGetFontFamilyForChars(int fd, const Pickle& pickle,
Expand Down Expand Up @@ -659,12 +650,13 @@ class SandboxIPCProcess {

const int lifeline_fd_;
const int browser_socket_;
scoped_ptr<FontConfigDirect> font_config_;
std::vector<std::string> sandbox_cmd_;
scoped_ptr<WebKitPlatformSupportImpl> webkit_platform_support_;
SkTDArray<SkString*> paths_;
};

SandboxIPCProcess::~SandboxIPCProcess() {
paths_.deleteAll();
if (webkit_platform_support_.get())
WebKit::shutdown();
}
Expand Down
70 changes: 29 additions & 41 deletions content/common/font_config_ipc_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "base/pickle.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/core/SkStream.h"

namespace content {

Expand All @@ -23,31 +25,21 @@ FontConfigIPC::~FontConfigIPC() {
close(fd_);
}

bool FontConfigIPC::Match(std::string* result_family,
unsigned* result_filefaceid,
bool filefaceid_valid, unsigned filefaceid,
const std::string& family,
const void* characters, size_t characters_bytes,
bool* is_bold, bool* is_italic) {
if (family.length() > kMaxFontFamilyLength)
bool FontConfigIPC::matchFamilyName(const char familyName[],
SkTypeface::Style requestedStyle,
FontIdentity* outFontIdentity,
SkString* outFamilyName,
SkTypeface::Style* outStyle) {
size_t familyNameLen = familyName ? strlen(familyName) : 0;
if (familyNameLen > kMaxFontFamilyLength)
return false;

Pickle request;
request.WriteInt(METHOD_MATCH);
request.WriteBool(filefaceid_valid);
if (filefaceid_valid)
request.WriteUInt32(filefaceid);
request.WriteData(familyName, familyNameLen);
request.WriteUInt32(requestedStyle);

request.WriteBool(is_bold && *is_bold);
request.WriteBool(is_bold && *is_italic);

request.WriteUInt32(characters_bytes);
if (characters_bytes)
request.WriteBytes(characters, characters_bytes);

request.WriteString(family);

uint8_t reply_buf[512];
uint8_t reply_buf[2048];
const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf,
sizeof(reply_buf), NULL,
request);
Expand All @@ -62,33 +54,29 @@ bool FontConfigIPC::Match(std::string* result_family,
if (!result)
return false;

uint32_t reply_filefaceid;
std::string reply_family;
bool resulting_bold, resulting_italic;
if (!reply.ReadUInt32(&iter, &reply_filefaceid) ||
!reply.ReadString(&iter, &reply_family) ||
!reply.ReadBool(&iter, &resulting_bold) ||
!reply.ReadBool(&iter, &resulting_italic)) {
SkString reply_family;
FontIdentity reply_identity;
uint32_t reply_style;
if (!skia::ReadSkString(reply, &iter, &reply_family) ||
!skia::ReadSkFontIdentity(reply, &iter, &reply_identity) ||
!reply.ReadUInt32(&iter, &reply_style)) {
return false;
}

if (result_filefaceid)
*result_filefaceid = reply_filefaceid;
if (result_family)
*result_family = reply_family;

if (is_bold)
*is_bold = resulting_bold;
if (is_italic)
*is_italic = resulting_italic;
if (outFontIdentity)
*outFontIdentity = reply_identity;
if (outFamilyName)
*outFamilyName = reply_family;
if (outStyle)
*outStyle = static_cast<SkTypeface::Style>(reply_style);

return true;
}

int FontConfigIPC::Open(unsigned filefaceid) {
SkStream* FontConfigIPC::openStream(const FontIdentity& identity) {
Pickle request;
request.WriteInt(METHOD_OPEN);
request.WriteUInt32(filefaceid);
request.WriteUInt32(identity.fID);

int result_fd = -1;
uint8_t reply_buf[256];
Expand All @@ -97,7 +85,7 @@ int FontConfigIPC::Open(unsigned filefaceid) {
&result_fd, request);

if (r == -1)
return -1;
return NULL;

Pickle reply(reinterpret_cast<char*>(reply_buf), r);
bool result;
Expand All @@ -106,10 +94,10 @@ int FontConfigIPC::Open(unsigned filefaceid) {
!result) {
if (result_fd)
close(result_fd);
return -1;
return NULL;
}

return result_fd;
return new SkFDStream(result_fd, true);
}

} // namespace content
25 changes: 13 additions & 12 deletions content/common/font_config_ipc_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,36 @@
#define CONTENT_COMMON_FONT_CONFIG_IPC_LINUX_H_

#include "base/compiler_specific.h"
#include "skia/ext/SkFontHost_fontconfig_impl.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"

#include <string>

namespace content {

// FontConfig implementation for Skia that proxies out of process to get out
// of the sandbox. See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
class FontConfigIPC : public FontConfigInterface {
class FontConfigIPC : public SkFontConfigInterface {
public:
explicit FontConfigIPC(int fd);
virtual ~FontConfigIPC();

// FontConfigInterface implementation.
virtual bool Match(std::string* result_family,
unsigned* result_filefaceid,
bool filefaceid_valid,
unsigned filefaceid,
const std::string& family,
const void* characters,
size_t characters_bytes,
bool* is_bold, bool* is_italic) OVERRIDE;
virtual int Open(unsigned filefaceid) OVERRIDE;
virtual bool matchFamilyName(const char familyName[],
SkTypeface::Style requested,
FontIdentity* outFontIdentifier,
SkString* outFamilyName,
SkTypeface::Style* outStyle) OVERRIDE;

virtual SkStream* openStream(const FontIdentity&) OVERRIDE;

enum Method {
METHOD_MATCH = 0,
METHOD_OPEN = 1,
};

enum {
kMaxFontFamilyLength = 2048
};

private:
const int fd_;
};
Expand Down
10 changes: 5 additions & 5 deletions content/zygote/zygote_main_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
#include "crypto/nss_util.h"
#include "sandbox/linux/services/libc_urandom_override.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#include "skia/ext/SkFontHost_fontconfig_control.h"
#include "third_party/icu/public/i18n/unicode/timezone.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"

#if defined(OS_LINUX)
#include <sys/epoll.h>
Expand Down Expand Up @@ -368,8 +368,8 @@ static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
return false;

PreSandboxInit();
SkiaFontConfigSetImplementation(
new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor));
SkFontConfigInterface::SetGlobal(
new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor))->unref();

if (setuid_sandbox->IsSuidSandboxChild()) {
// Use the SUID sandbox. This still allows the seccomp sandbox to
Expand Down Expand Up @@ -438,8 +438,8 @@ static bool EnterSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
return false;

PreSandboxInit();
SkiaFontConfigSetImplementation(
new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor));
SkFontConfigInterface::SetGlobal(
new FontConfigIPC(Zygote::kMagicSandboxIPCDescriptor)))->unref();
return true;
}

Expand Down
Loading

0 comments on commit 9628e0d

Please sign in to comment.