summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 18:15:08 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 18:15:08 +0000
commitabe3ad93b1996ad1b1aff121dbce6be533e579c3 (patch)
tree635542dd62d6b7df4c05a3c39f2c737730e23376
parent89d156b666af4d4f4c83579be31e9092155bbaf7 (diff)
downloadchromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.zip
chromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.tar.gz
chromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.tar.bz2
Linux: Add support for chrooted renderers.
http://code.google.com/p/chromium/wiki/LinuxSandboxIPC Without filesystem access from the renderers, we need another way of dealing with fontconfig and font loading. This add support for: * An "SBX_D" environment variable in the renderers which is used to signal the end of dynamic linking so that the chroot can be enforced. * A sandbox_host process, running outside the sandbox, to deal with fontconfig requests from the renderers. See the wiki page for the reasoning behind making it a separate process. * A new, custom SkFontHost for Skia. Because this is Chrome specific, it will live outside the upstream Skia tree. This FontHost can be configured either to drive fontconfig directly (for the browser process and for any unsandboxed renderers) or to use an IPC system. Since the same SkFontHost has to be linked into both the browser and renderer (they are the same binary), this switch has to be made at run time. Sandbox IPC calls are rare (a couple of dozen at page load time) and add about 50us of overhead for each call. (Reland of r17575 which was reverted in r17577) http://codereview.chromium.org/112074 BUG=8081 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18405 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/process_util_linux.cc5
-rw-r--r--chrome/app/chrome_dll_main.cc14
-rw-r--r--chrome/app/chrome_main_uitest.cc5
-rw-r--r--chrome/browser/renderer_host/render_sandbox_host_linux.cc226
-rw-r--r--chrome/browser/renderer_host/render_sandbox_host_linux.h34
-rw-r--r--chrome/browser/zygote_host_linux.cc6
-rw-r--r--chrome/browser/zygote_main_linux.cc57
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/common/chrome_descriptors.h1
-rw-r--r--skia/ext/SkFontHost_fontconfig.cpp237
-rw-r--r--skia/ext/SkFontHost_fontconfig_control.h26
-rw-r--r--skia/ext/SkFontHost_fontconfig_direct.cpp180
-rw-r--r--skia/ext/SkFontHost_fontconfig_direct.h44
-rw-r--r--skia/ext/SkFontHost_fontconfig_impl.h60
-rw-r--r--skia/ext/SkFontHost_fontconfig_ipc.cpp144
-rw-r--r--skia/ext/SkFontHost_fontconfig_ipc.h74
-rwxr-xr-xskia/skia.gyp8
17 files changed, 1103 insertions, 20 deletions
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index 7560257..a5337b4 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -102,6 +102,11 @@ bool LaunchApp(const std::vector<std::string>& argv,
if (!ShuffleFileDescriptors(fd_shuffle))
exit(127);
+ // If we are using the SUID sandbox, it sets a magic environment variable
+ // ("SBX_D"), so we remove that variable from the environment here on the
+ // off chance that it's already set.
+ unsetenv("SBX_D");
+
CloseSuperfluousFds(fd_shuffle);
scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index 4759d02..c22d05c 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -425,20 +425,6 @@ int ChromeMain(int argc, const char** argv) {
InitCrashReporter();
#endif
-#if defined(OS_POSIX)
- // Bug 11776: we mistakenly created directories world-readable.
- // Fix old instances of these directories manually.
- // TODO(evanm): remove this code in a month or two.
- if (user_data_dir.empty()) {
- FilePath fix_dir;
- CHECK(PathService::Get(chrome::DIR_USER_DATA, &fix_dir));
- struct stat statbuf;
- CHECK(stat(fix_dir.value().c_str(), &statbuf) == 0);
- if ((statbuf.st_mode & 0077) != 0)
- CHECK(chmod(fix_dir.value().c_str(), 0700) == 0);
- }
-#endif
-
bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
// This is an unsupported and not fully tested mode, so don't enable it for
diff --git a/chrome/app/chrome_main_uitest.cc b/chrome/app/chrome_main_uitest.cc
index f229751..ea0bbc7 100644
--- a/chrome/app/chrome_main_uitest.cc
+++ b/chrome/app/chrome_main_uitest.cc
@@ -19,8 +19,9 @@ TEST_F(ChromeMainTest, AppLaunch) {
EXPECT_EQ(1, UITest::GetBrowserProcessCount());
} else {
#if defined(OS_LINUX)
- // On Linux we'll have three processes: browser, renderer and zygote.
- EXPECT_EQ(3, UITest::GetBrowserProcessCount());
+ // On Linux we'll have four processes: browser, renderer, zygote and
+ // sandbox helper.
+ EXPECT_EQ(4, UITest::GetBrowserProcessCount());
#else
// We should have two instances of the browser process alive -
// one is the Browser and the other is the Renderer.
diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.cc b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
new file mode 100644
index 0000000..c0ca6f6
--- /dev/null
+++ b/chrome/browser/renderer_host/render_sandbox_host_linux.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2009 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 "chrome/browser/renderer_host/render_sandbox_host_linux.h"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/process_util.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/pickle.h"
+#include "base/unix_domain_socket_posix.h"
+
+#include "SkFontHost_fontconfig_direct.h"
+#include "SkFontHost_fontconfig_ipc.h"
+
+// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+
+// BEWARE: code in this file run across *processes* (not just threads).
+
+// This code runs in a child process
+class SandboxIPCProcess {
+ public:
+ // lifeline_fd: this is the read end of a pipe which the browser process
+ // holds the other end of. If the browser process dies, it's descriptors are
+ // closed and we will noticed an EOF on the pipe. That's our signal to exit.
+ // browser_socket: the 'browser's end of the sandbox IPC socketpair. From the
+ // point of view of the renderer's, it's talking to the browser but this
+ // object actually services the requests.
+ SandboxIPCProcess(int lifeline_fd, int browser_socket)
+ : lifeline_fd_(lifeline_fd),
+ browser_socket_(browser_socket),
+ font_config_(new FontConfigDirect()) {
+ base::InjectiveMultimap multimap;
+ multimap.push_back(base::InjectionArc(0, lifeline_fd, false));
+ multimap.push_back(base::InjectionArc(0, browser_socket, false));
+
+ base::CloseSuperfluousFds(multimap);
+ }
+
+ void Run() {
+ struct pollfd pfds[2];
+ pfds[0].fd = lifeline_fd_;
+ pfds[0].events = POLLIN;
+ pfds[1].fd = browser_socket_;
+ pfds[1].events = POLLIN;
+
+ bool failed_polls = 0;
+ for (;;) {
+ const int r = HANDLE_EINTR(poll(pfds, 2, -1));
+ if (r < 1) {
+ LOG(WARNING) << "poll errno:" << errno;
+ if (failed_polls++ == 3) {
+ LOG(FATAL) << "poll failing. Sandbox host aborting.";
+ return;
+ }
+ continue;
+ }
+
+ failed_polls = 0;
+
+ if (pfds[0].revents) {
+ // our parent died so we should too.
+ _exit(0);
+ }
+
+ if (pfds[1].revents) {
+ HandleRequestFromRenderer(browser_socket_);
+ }
+ }
+ }
+
+ private:
+ // ---------------------------------------------------------------------------
+ // Requests from the renderer...
+
+ void HandleRequestFromRenderer(int fd) {
+ std::vector<int> fds;
+ static const unsigned kMaxMessageLength = 2048;
+ char buf[kMaxMessageLength];
+ const ssize_t len = base::RecvMsg(fd, buf, sizeof(buf), &fds);
+ if (len == -1)
+ return;
+ if (fds.size() == 0)
+ return;
+
+ Pickle pickle(buf, len);
+ void* iter = NULL;
+
+ int kind;
+ if (!pickle.ReadInt(&iter, &kind))
+ goto error;
+
+ if (kind == FontConfigIPC::METHOD_MATCH) {
+ HandleFontMatchRequest(fd, pickle, iter, fds);
+ } else if (kind == FontConfigIPC::METHOD_OPEN) {
+ HandleFontOpenRequest(fd, pickle, iter, fds);
+ }
+
+ error:
+ for (std::vector<int>::const_iterator
+ i = fds.begin(); i != fds.end(); ++i) {
+ close(*i);
+ }
+ }
+
+ void HandleFontMatchRequest(int fd, Pickle& pickle, void* iter,
+ std::vector<int>& fds) {
+ bool fileid_valid;
+ uint32_t fileid;
+ bool is_bold, is_italic;
+ std::string family;
+
+ if (!pickle.ReadBool(&iter, &fileid_valid))
+ return;
+ if (fileid_valid) {
+ if (!pickle.ReadUInt32(&iter, &fileid))
+ return;
+ }
+ if (!pickle.ReadBool(&iter, &is_bold) ||
+ !pickle.ReadBool(&iter, &is_italic) ||
+ !pickle.ReadString(&iter, &family)) {
+ return;
+ }
+
+ std::string result_family;
+ unsigned result_fileid;
+
+ const bool r = font_config_->Match(
+ &result_family, &result_fileid, fileid_valid, fileid, family, is_bold,
+ is_italic);
+
+ Pickle reply;
+ if (!r) {
+ reply.WriteBool(false);
+ } else {
+ reply.WriteBool(true);
+ reply.WriteUInt32(result_fileid);
+ reply.WriteString(result_family);
+ }
+ SendRendererReply(fds, reply, -1);
+ }
+
+ void HandleFontOpenRequest(int fd, Pickle& pickle, void* iter,
+ std::vector<int>& fds) {
+ uint32_t fileid;
+ if (!pickle.ReadUInt32(&iter, &fileid))
+ return;
+ const int result_fd = font_config_->Open(fileid);
+
+ Pickle reply;
+ if (result_fd == -1) {
+ reply.WriteBool(false);
+ } else {
+ reply.WriteBool(true);
+ }
+
+ SendRendererReply(fds, reply, result_fd);
+ }
+
+ void SendRendererReply(const std::vector<int>& fds, const Pickle& reply,
+ int reply_fd) {
+ struct msghdr msg;
+ memset(&msg, 0, sizeof(msg));
+ struct iovec iov = {const_cast<void*>(reply.data()), reply.size()};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ char control_buffer[CMSG_SPACE(sizeof(int))];
+
+ if (reply_fd != -1) {
+ struct cmsghdr *cmsg;
+
+ msg.msg_control = control_buffer;
+ msg.msg_controllen = sizeof(control_buffer);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &reply_fd, sizeof(int));
+ msg.msg_controllen = cmsg->cmsg_len;
+ }
+
+ HANDLE_EINTR(sendmsg(fds[0], &msg, MSG_DONTWAIT));
+ }
+
+ // ---------------------------------------------------------------------------
+
+ const int lifeline_fd_;
+ const int browser_socket_;
+ FontConfigDirect* const font_config_;
+};
+
+// -----------------------------------------------------------------------------
+
+// Runs on the main thread at startup.
+RenderSandboxHostLinux::RenderSandboxHostLinux() {
+ int fds[2];
+ CHECK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0);
+
+ renderer_socket_ = fds[0];
+ const int browser_socket = fds[1];
+
+ int pipefds[2];
+ CHECK(0 == pipe(pipefds));
+ const int child_lifeline_fd = pipefds[0];
+ childs_lifeline_fd_ = pipefds[1];
+
+ const pid_t child = fork();
+ if (child == 0) {
+ SandboxIPCProcess handler(child_lifeline_fd, browser_socket);
+ handler.Run();
+ _exit(0);
+ }
+}
+
+RenderSandboxHostLinux::~RenderSandboxHostLinux() {
+ HANDLE_EINTR(close(renderer_socket_));
+ HANDLE_EINTR(close(childs_lifeline_fd_));
+}
diff --git a/chrome/browser/renderer_host/render_sandbox_host_linux.h b/chrome/browser/renderer_host/render_sandbox_host_linux.h
new file mode 100644
index 0000000..43fa447
--- /dev/null
+++ b/chrome/browser/renderer_host/render_sandbox_host_linux.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2009 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.
+
+// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_SANDBOX_HOST_LINUX_H_
+#define CHROME_BROWSER_RENDERER_HOST_RENDER_SANDBOX_HOST_LINUX_H_
+
+#include "base/singleton.h"
+#include "base/thread.h"
+#include "base/message_loop.h"
+
+// This is a singleton object which handles sandbox requests from the
+// renderers.
+class RenderSandboxHostLinux {
+ public:
+ // Get the file descriptor which renderers should be given in order to signal
+ // crashes to the browser.
+ int GetRendererSocket() const { return renderer_socket_; }
+
+ private:
+ friend struct DefaultSingletonTraits<RenderSandboxHostLinux>;
+ // This object must be constructed on the main thread.
+ RenderSandboxHostLinux();
+ ~RenderSandboxHostLinux();
+
+ int renderer_socket_;
+ int childs_lifeline_fd_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(RenderSandboxHostLinux);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_SANDBOX_HOST_LINUX_H_
diff --git a/chrome/browser/zygote_host_linux.cc b/chrome/browser/zygote_host_linux.cc
index f56e6e93..1c582a3 100644
--- a/chrome/browser/zygote_host_linux.cc
+++ b/chrome/browser/zygote_host_linux.cc
@@ -16,6 +16,7 @@
#include "base/process_util.h"
#include "base/unix_domain_socket_posix.h"
+#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
#include "chrome/common/chrome_switches.h"
ZygoteHost::ZygoteHost() {
@@ -38,6 +39,11 @@ ZygoteHost::ZygoteHost() {
cmd_line.PrependWrapper(prefix);
}
+ // Start up the sandbox host process and get the file descriptor for the
+ // renderers to talk to it.
+ const int sfd = Singleton<RenderSandboxHostLinux>()->GetRendererSocket();
+ fds_to_map.push_back(std::make_pair(sfd, 4));
+
base::ProcessHandle process;
base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process);
CHECK(process != -1) << "Failed to launch zygote process";
diff --git a/chrome/browser/zygote_main_linux.cc b/chrome/browser/zygote_main_linux.cc
index d450c39..6d15c0f 100644
--- a/chrome/browser/zygote_main_linux.cc
+++ b/chrome/browser/zygote_main_linux.cc
@@ -7,6 +7,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
+#include <sys/prctl.h>
#include "base/command_line.h"
#include "base/eintr_wrapper.h"
@@ -19,6 +20,8 @@
#include "chrome/common/main_function_params.h"
#include "chrome/common/process_watcher.h"
+#include "skia/ext/SkFontHost_fontconfig_control.h"
+
// http://code.google.com/p/chromium/wiki/LinuxZygote
// This is the object which implements the zygote. The ZygoteMain function,
@@ -29,6 +32,8 @@ class Zygote {
bool ProcessRequests() {
// A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
// browser on it.
+ // A SOCK_DGRAM is installed in fd 4. This is the sandbox IPC channel.
+ // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
// We need to accept SIGCHLD, even though our handler is a no-op because
// otherwise we cannot wait on children. (According to POSIX 2001.)
@@ -54,7 +59,7 @@ class Zygote {
// new process and thus need to unwind back into ChromeMain.
bool HandleRequestFromBrowser(int fd) {
std::vector<int> fds;
- static const unsigned kMaxMessageLength = 2048;
+ static const unsigned kMaxMessageLength = 1024;
char buf[kMaxMessageLength];
const ssize_t len = base::RecvMsg(fd, buf, sizeof(buf), &fds);
if (len == -1) {
@@ -135,6 +140,9 @@ class Zygote {
mapping.push_back(std::make_pair(key, fds[i]));
}
+ mapping.push_back(std::make_pair(
+ static_cast<uint32_t>(kSandboxIPCChannel), 4));
+
child = fork();
if (!child) {
@@ -159,10 +167,55 @@ class Zygote {
close(*i);
return false;
}
- // ---------------------------------------------------------------------------
};
+static bool MaybeEnterChroot() {
+ const char* const sandbox_fd_string = getenv("SBX_D");
+ if (sandbox_fd_string) {
+ // The SUID sandbox sets this environment variable to a file descriptor
+ // over which we can signal that we have completed our startup and can be
+ // chrooted.
+
+ char* endptr;
+ const long fd_long = strtol(sandbox_fd_string, &endptr, 10);
+ if (!*sandbox_fd_string || *endptr || fd_long < 0 || fd_long > INT_MAX)
+ return false;
+ const int fd = fd_long;
+
+ static const char kChrootMe = 'C';
+ static const char kChrootMeSuccess = 'O';
+
+ if (HANDLE_EINTR(write(fd, &kChrootMe, 1)) != 1)
+ return false;
+
+ char reply;
+ if (HANDLE_EINTR(read(fd, &reply, 1)) != 1)
+ return false;
+ if (reply != kChrootMeSuccess)
+ return false;
+ if (chdir("/") == -1)
+ return false;
+
+ static const int kMagicSandboxIPCDescriptor = 4;
+ SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor);
+
+ prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
+ return false;
+ } else {
+ SkiaFontConfigUseDirectImplementation();
+ }
+
+ return true;
+}
+
bool ZygoteMain(const MainFunctionParams& params) {
+ if (!MaybeEnterChroot()) {
+ LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
+ << errno << ")";
+ return false;
+ }
+
Zygote zygote;
return zygote.ProcessRequests();
}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 4cd57bd..bed25c9 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1229,6 +1229,8 @@
'browser/renderer_host/download_throttling_resource_handler.h',
'browser/renderer_host/render_process_host.cc',
'browser/renderer_host/render_process_host.h',
+ 'browser/renderer_host/render_sandbox_host_linux.h',
+ 'browser/renderer_host/render_sandbox_host_linux.cc',
'browser/renderer_host/render_view_host.cc',
'browser/renderer_host/render_view_host.h',
'browser/renderer_host/render_view_host_delegate.h',
diff --git a/chrome/common/chrome_descriptors.h b/chrome/common/chrome_descriptors.h
index 3d6be45..c86eee5 100644
--- a/chrome/common/chrome_descriptors.h
+++ b/chrome/common/chrome_descriptors.h
@@ -10,6 +10,7 @@
enum {
kPrimaryIPCChannel = 0,
kCrashDumpSignal = 1,
+ kSandboxIPCChannel = 2, // http://code.google.com/p/chromium/LinuxSandboxIPC
};
#endif // CHROME_COMMON_CHROME_DESCRIPTORS_H_
diff --git a/skia/ext/SkFontHost_fontconfig.cpp b/skia/ext/SkFontHost_fontconfig.cpp
new file mode 100644
index 0000000..04ac5b9d
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig.cpp
@@ -0,0 +1,237 @@
+/* libs/graphics/ports/SkFontHost_fontconfig.cpp
+**
+** Copyright 2008, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// -----------------------------------------------------------------------------
+// This file provides implementations of the font resolution members of
+// SkFontHost by using the fontconfig[1] library. Fontconfig is usually found
+// on Linux systems and handles configuration, parsing and caching issues
+// involved with enumerating and matching fonts.
+//
+// [1] http://fontconfig.org
+// -----------------------------------------------------------------------------
+
+#include <map>
+#include <string>
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "SkFontHost.h"
+#include "SkStream.h"
+#include "SkFontHost_fontconfig_impl.h"
+#include "SkFontHost_fontconfig_direct.h"
+#include "SkFontHost_fontconfig_ipc.h"
+
+static FontConfigInterface* global_fc_impl = NULL;
+
+void SkiaFontConfigUseDirectImplementation() {
+ if (global_fc_impl)
+ delete global_fc_impl;
+ global_fc_impl = new FontConfigDirect;
+}
+
+void SkiaFontConfigUseIPCImplementation(int fd) {
+ if (global_fc_impl)
+ delete global_fc_impl;
+ global_fc_impl = new FontConfigIPC(fd);
+}
+
+static FontConfigInterface* GetFcImpl() {
+ if (!global_fc_impl)
+ global_fc_impl = new FontConfigDirect;
+ return global_fc_impl;
+}
+
+static SkMutex global_fc_map_lock;
+static std::map<uint32_t, SkTypeface *> global_fc_typefaces;
+
+// This is the maximum size of the font cache.
+static const unsigned kFontCacheMemoryBudget = 2 * 1024 * 1024; // 2MB
+
+// UniqueIds are encoded as (fileid << 8) | style
+
+static unsigned UniqueIdToFileId(unsigned uniqueid)
+{
+ return uniqueid >> 8;
+}
+
+static SkTypeface::Style UniqueIdToStyle(unsigned uniqueid)
+{
+ return static_cast<SkTypeface::Style>(uniqueid & 0xff);
+}
+
+static unsigned FileIdAndStyleToUniqueId(unsigned fileid,
+ SkTypeface::Style style)
+{
+ SkASSERT(style & 0xff == style);
+ return (fileid << 8) | static_cast<int>(style);
+}
+
+class FontConfigTypeface : public SkTypeface {
+public:
+ FontConfigTypeface(Style style, uint32_t id)
+ : SkTypeface(style, id)
+ { }
+};
+
+// static
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+ const char familyName[],
+ SkTypeface::Style style)
+{
+ std::string resolved_family_name;
+
+ if (familyFace) {
+ // Given the fileid we can ask fontconfig for the familyname of the
+ // font.
+ const unsigned fileid = UniqueIdToFileId(familyFace->uniqueID());
+ if (!GetFcImpl()->Match(
+ &resolved_family_name, NULL, true /* fileid valid */, fileid, "",
+ -1, -1)) {
+ return NULL;
+ }
+ } else if (familyName) {
+ resolved_family_name = familyName;
+ } else {
+ return NULL;
+ }
+
+ const bool bold = style & SkTypeface::kBold;
+ const bool italic = style & SkTypeface::kItalic;
+ unsigned fileid;
+ if (!GetFcImpl()->Match(NULL, &fileid, false, -1, /* no fileid */
+ resolved_family_name, bold, italic)) {
+ return NULL;
+ }
+
+ const unsigned id = FileIdAndStyleToUniqueId(fileid, style);
+ SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (style, id));
+
+ {
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+ global_fc_typefaces[id] = typeface;
+ }
+
+ return typeface;
+}
+
+// static
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream)
+{
+ SkASSERT(!"SkFontHost::CreateTypefaceFromStream unimplemented");
+ return NULL;
+}
+
+// static
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[])
+{
+ SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");
+ return NULL;
+}
+
+// static
+bool SkFontHost::ValidFontID(SkFontID uniqueID) {
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+ return global_fc_typefaces.find(uniqueID) != global_fc_typefaces.end();
+}
+
+void SkFontHost::Serialize(const SkTypeface*, SkWStream*) {
+ SkASSERT(!"SkFontHost::Serialize unimplemented");
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+ SkASSERT(!"SkFontHost::Deserialize unimplemented");
+ return NULL;
+}
+
+// static
+uint32_t SkFontHost::NextLogicalFont(SkFontID fontID) {
+ // We don't handle font fallback, WebKit does.
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkFileDescriptorStream : public SkStream {
+ public:
+ SkFileDescriptorStream(int fd)
+ : fd_(fd) {
+ }
+
+ ~SkFileDescriptorStream() {
+ close(fd_);
+ }
+
+ virtual bool rewind() {
+ if (lseek(fd_, 0, SEEK_SET) == -1)
+ return false;
+ return true;
+ }
+
+ // SkStream implementation.
+ virtual size_t read(void* buffer, size_t size) {
+ if (!buffer && !size) {
+ // This is request for the length of the stream.
+ struct stat st;
+ if (fstat(fd_, &st) == -1)
+ return 0;
+ return st.st_size;
+ }
+
+ if (!buffer) {
+ // This is a request to skip bytes.
+ const off_t current_position = lseek(fd_, 0, SEEK_CUR);
+ if (current_position == -1)
+ return 0;
+ const off_t new_position = lseek(fd_, size, SEEK_CUR);
+ if (new_position == -1)
+ return 0;
+ if (new_position < current_position) {
+ lseek(fd_, current_position, SEEK_SET);
+ return 0;
+ }
+ return new_position;
+ }
+
+ // This is a request to read bytes.
+ return ::read(fd_, buffer, size);
+ }
+
+ private:
+ const int fd_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// static
+SkStream* SkFontHost::OpenStream(uint32_t id)
+{
+ const unsigned fileid = UniqueIdToFileId(id);
+ const int fd = GetFcImpl()->Open(fileid);
+ if (fd < 0)
+ return NULL;
+
+ return SkNEW_ARGS(SkFileDescriptorStream, (fd));
+}
+
+size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar)
+{
+ if (sizeAllocatedSoFar > kFontCacheMemoryBudget)
+ return sizeAllocatedSoFar - kFontCacheMemoryBudget;
+ else
+ return 0; // nothing to do
+}
diff --git a/skia/ext/SkFontHost_fontconfig_control.h b/skia/ext/SkFontHost_fontconfig_control.h
new file mode 100644
index 0000000..2af6c2e
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_control.h
@@ -0,0 +1,26 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_control.h
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef FontConfigControl_DEFINED
+#define FontConfigControl_DEFINED
+
+// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+
+extern void SkiaFontConfigUseDirectImplementation();
+extern void SkiaFontConfigUseIPCImplementation(int fd);
+
+#endif // FontConfigControl_DEFINED
diff --git a/skia/ext/SkFontHost_fontconfig_direct.cpp b/skia/ext/SkFontHost_fontconfig_direct.cpp
new file mode 100644
index 0000000..001fccd
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_direct.cpp
@@ -0,0 +1,180 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_direct.cpp
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "SkFontHost_fontconfig_direct.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <fontconfig/fontconfig.h>
+
+FontConfigDirect::FontConfigDirect()
+ : next_file_id_(0) {
+ FcInit();
+}
+
+// -----------------------------------------------------------------------------
+// Normally we only return exactly the font asked for. In last-resort cases,
+// the request is for one of the basic font names "Sans", "Serif" or
+// "Monospace". This function tells you whether a given request is for such a
+// fallback.
+// -----------------------------------------------------------------------------
+static bool IsFallbackFontAllowed(const std::string& family)
+{
+ return family == "Sans" ||
+ family == "Serif" ||
+ family == "Monospace";
+}
+
+bool FontConfigDirect::Match(std::string* result_family,
+ unsigned* result_fileid,
+ bool fileid_valid, unsigned fileid,
+ const std::string& family, int is_bold,
+ int is_italic) {
+ SkAutoMutexAcquire ac(mutex_);
+ FcPattern* pattern = FcPatternCreate();
+
+ FcValue fcvalue;
+ if (fileid_valid) {
+ const std::map<unsigned, std::string>::const_iterator
+ i = fileid_to_filename_.find(fileid);
+ if (i == fileid_to_filename_.end()) {
+ FcPatternDestroy(pattern);
+ return false;
+ }
+
+ fcvalue.type = FcTypeString;
+ fcvalue.u.s = (FcChar8*) i->second.c_str();
+ FcPatternAdd(pattern, FC_FILE, fcvalue, 0);
+ }
+ if (!family.empty()) {
+ fcvalue.type = FcTypeString;
+ fcvalue.u.s = (FcChar8*) family.c_str();
+ FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0);
+ }
+ if (is_bold > 0) {
+ fcvalue.type = FcTypeInteger;
+ fcvalue.u.i = is_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL;
+ FcPatternAdd(pattern, FC_WEIGHT, fcvalue, 0);
+ }
+ if (is_italic > 0) {
+ fcvalue.type = FcTypeInteger;
+ fcvalue.u.i = is_bold ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
+ FcPatternAdd(pattern, FC_SLANT, fcvalue, 0);
+ }
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ // Font matching:
+ // CSS often specifies a fallback list of families:
+ // font-family: a, b, c, serif;
+ // However, fontconfig will always do its best to find *a* font when asked
+ // for something so we need a way to tell if the match which it has found is
+ // "good enough" for us. Otherwise, we can return NULL which gets piped up
+ // and lets WebKit know to try the next CSS family name. However, fontconfig
+ // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
+ // wish to support that.
+ //
+ // Thus, if a specific family is requested we set @family_requested. Then we
+ // record two strings: the family name after config processing and the
+ // family name after resolving. If the two are equal, it's a good match.
+ //
+ // So consider the case where a user has mapped Arial to Helvetica in their
+ // config.
+ // requested family: "Arial"
+ // post_config_family: "Helvetica"
+ // post_match_family: "Helvetica"
+ // -> good match
+ //
+ // and for a missing font:
+ // requested family: "Monaco"
+ // post_config_family: "Monaco"
+ // post_match_family: "Times New Roman"
+ // -> BAD match
+ //
+ // However, we special-case fallback fonts; see IsFallbackFontAllowed().
+ FcChar8* post_config_family;
+ FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family);
+
+ FcResult result;
+ FcPattern* match = FcFontMatch(0, pattern, &result);
+ if (!match) {
+ FcPatternDestroy(pattern);
+ return false;
+ }
+
+ FcChar8* post_match_family;
+ FcPatternGetString(match, FC_FAMILY, 0, &post_match_family);
+ const bool family_names_match =
+ family.empty() ?
+ true :
+ strcasecmp((char *)post_config_family, (char *)post_match_family) == 0;
+
+ FcPatternDestroy(pattern);
+
+ if (!family_names_match && !IsFallbackFontAllowed(family)) {
+ FcPatternDestroy(match);
+ return false;
+ }
+
+ FcChar8* c_filename;
+ if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+ const std::string filename((char *) c_filename);
+
+ unsigned out_fileid;
+ if (fileid_valid) {
+ out_fileid = fileid;
+ } else {
+ const std::map<std::string, unsigned>::const_iterator
+ i = filename_to_fileid_.find(filename);
+ if (i == filename_to_fileid_.end()) {
+ out_fileid = next_file_id_++;
+ filename_to_fileid_[filename] = out_fileid;
+ fileid_to_filename_[out_fileid] = filename;
+ } else {
+ out_fileid = i->second;
+ }
+ }
+
+ if (*result_fileid)
+ *result_fileid = out_fileid;
+
+ FcChar8* c_family;
+ if (FcPatternGetString(match, FC_FAMILY, 0, &c_family)) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+
+ if (result_family)
+ *result_family = (char *) c_family;
+
+ return true;
+}
+
+int FontConfigDirect::Open(unsigned fileid) {
+ SkAutoMutexAcquire ac(mutex_);
+ const std::map<unsigned, std::string>::const_iterator
+ i = fileid_to_filename_.find(fileid);
+ if (i == fileid_to_filename_.end())
+ return -1;
+
+ return open(i->second.c_str(), O_RDONLY);
+}
diff --git a/skia/ext/SkFontHost_fontconfig_direct.h b/skia/ext/SkFontHost_fontconfig_direct.h
new file mode 100644
index 0000000..d9c934a
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_direct.h
@@ -0,0 +1,44 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_direct.h
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef FontConfigDirect_DEFINED
+#define FontConfigDirect_DEFINED
+
+#include <map>
+#include <string>
+
+#include "SkThread.h"
+#include "SkFontHost_fontconfig_impl.h"
+
+class FontConfigDirect : public FontConfigInterface {
+ public:
+ FontConfigDirect();
+
+ // FontConfigInterface implementation. Thread safe.
+ virtual bool Match(std::string* result_family, unsigned* result_fileid,
+ bool fileid_valid, unsigned fileid,
+ const std::string& family, int is_bold, int is_italic);
+ virtual int Open(unsigned fileid);
+
+ private:
+ SkMutex mutex_;
+ std::map<unsigned, std::string> fileid_to_filename_;
+ std::map<std::string, unsigned> filename_to_fileid_;
+ unsigned next_file_id_;
+};
+
+#endif // FontConfigDirect_DEFINED
diff --git a/skia/ext/SkFontHost_fontconfig_impl.h b/skia/ext/SkFontHost_fontconfig_impl.h
new file mode 100644
index 0000000..a593891
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_impl.h
@@ -0,0 +1,60 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_impl.h
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/* The SkFontHost_fontconfig code requires an implementation of an abstact
+ * fontconfig interface. We do this because sometimes fontconfig is not
+ * directly availible and this provides an ability to change the fontconfig
+ * implementation at run-time.
+ */
+
+#ifndef FontConfigInterface_DEFINED
+#define FontConfigInterface_DEFINED
+
+#include <string>
+
+class FontConfigInterface {
+ public:
+ virtual ~FontConfigInterface() { }
+
+ /** Performs config match
+ *
+ * @param result_family (output) on success, the resulting family name.
+ * @param result_fileid (output) on success, the resulting file id.
+ * @param fileid_valid if true, then |fileid| is valid
+ * @param fileid the fileid (as returned by this function) which we are
+ * trying to match.
+ * @param family (optional) the family of the font that we are trying to
+ * match.
+ * @param is_bold (optional, set to -1 to ignore)
+ * @param is_italic (optional, set to -1 to ignore)
+ * @return true iff successful.
+ */
+ virtual bool Match(
+ std::string* result_family,
+ unsigned* result_fileid,
+ bool fileid_valid,
+ unsigned fileid,
+ const std::string& family,
+ int is_bold,
+ int is_italic) = 0;
+
+ /** Open a font file given the fileid as returned by Match
+ */
+ virtual int Open(unsigned fileid) = 0;
+};
+
+#endif // FontConfigInterface_DEFINED
diff --git a/skia/ext/SkFontHost_fontconfig_ipc.cpp b/skia/ext/SkFontHost_fontconfig_ipc.cpp
new file mode 100644
index 0000000..1705aed
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_ipc.cpp
@@ -0,0 +1,144 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_direct.cpp
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+
+#include "SkFontHost_fontconfig_ipc.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include "base/pickle.h"
+#include "base/unix_domain_socket_posix.h"
+
+FontConfigIPC::FontConfigIPC(int fd)
+ : fd_(fd) {
+}
+
+FontConfigIPC::~FontConfigIPC() {
+ close(fd_);
+}
+
+static ssize_t SyncIPC(int fd, uint8_t* reply, unsigned reply_len, int* result_fd,
+ const Pickle& request) {
+ int fds[2];
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == -1)
+ return false;
+
+ std::vector<int> fd_vector;
+ fd_vector.push_back(fds[1]);
+ if (!base::SendMsg(fd, request.data(), request.size(), fd_vector)) {
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+ close(fds[1]);
+
+ fd_vector.clear();
+ const ssize_t r = base::RecvMsg(fds[0], reply, reply_len, &fd_vector);
+ close(fds[0]);
+ if (r == -1)
+ return -1;
+
+ if ((fd_vector.size() > 0 && result_fd == NULL) || fd_vector.size() > 1) {
+ for (std::vector<int>::const_iterator
+ i = fd_vector.begin(); i != fd_vector.end(); ++i) {
+ close(*i);
+ }
+
+ return -1;
+ }
+
+ if (result_fd) {
+ if (fd_vector.size() == 0) {
+ *result_fd = -1;
+ } else {
+ *result_fd = fd_vector[0];
+ }
+ }
+
+ return r;
+}
+
+bool FontConfigIPC::Match(std::string* result_family,
+ unsigned* result_fileid,
+ bool fileid_valid, unsigned fileid,
+ const std::string& family, int is_bold,
+ int is_italic) {
+ Pickle request;
+ request.WriteInt(METHOD_MATCH);
+ request.WriteBool(fileid_valid);
+ if (fileid_valid)
+ request.WriteUInt32(fileid);
+ request.WriteBool(is_bold);
+ request.WriteBool(is_italic);
+ request.WriteString(family);
+
+ uint8_t reply_buf[512];
+ const ssize_t r = SyncIPC(fd_, reply_buf, sizeof(reply_buf), NULL, request);
+ if (r == -1)
+ return false;
+
+ Pickle reply(reinterpret_cast<char*>(reply_buf), r);
+ void* iter = NULL;
+ bool result;
+ if (!reply.ReadBool(&iter, &result))
+ return false;
+ if (!result)
+ return false;
+
+ uint32_t reply_fileid;
+ std::string reply_family;
+ if (!reply.ReadUInt32(&iter, &reply_fileid) ||
+ !reply.ReadString(&iter, &reply_family)) {
+ return false;
+ }
+
+ *result_fileid = reply_fileid;
+ if (result_family)
+ *result_family = reply_family;
+
+ return true;
+}
+
+int FontConfigIPC::Open(unsigned fileid) {
+ Pickle request;
+ request.WriteInt(METHOD_OPEN);
+ request.WriteUInt32(fileid);
+
+ int result_fd = -1;
+ uint8_t reply_buf[256];
+ const ssize_t r = SyncIPC(fd_, reply_buf, sizeof(reply_buf), &result_fd, request);
+
+ if (r == -1)
+ return -1;
+
+ Pickle reply(reinterpret_cast<char*>(reply_buf), r);
+ bool result;
+ void* iter = NULL;
+ if (!reply.ReadBool(&iter, &result) ||
+ !result) {
+ if (result_fd)
+ close(result_fd);
+ return -1;
+ }
+
+ return result_fd;
+}
diff --git a/skia/ext/SkFontHost_fontconfig_ipc.h b/skia/ext/SkFontHost_fontconfig_ipc.h
new file mode 100644
index 0000000..5efd1ee
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_ipc.h
@@ -0,0 +1,74 @@
+/* libs/graphics/ports/SkFontHost_fontconfig_ipc.h
+**
+** Copyright 2009, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef FontConfigIPC_DEFINED
+#define FontConfigIPC_DEFINED
+
+// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+
+#include <map>
+#include <string>
+
+#include "SkFontHost_fontconfig_impl.h"
+
+class FontConfigIPC : public FontConfigInterface {
+ public:
+ FontConfigIPC(int fd);
+ ~FontConfigIPC();
+
+ // FontConfigInterface implementation.
+ virtual bool Match(std::string* result_family, unsigned* result_fileid,
+ bool fileid_valid, unsigned fileid,
+ const std::string& family, int is_bold, int is_italic);
+ virtual int Open(unsigned fileid);
+
+ enum Method {
+ METHOD_MATCH = 0,
+ METHOD_OPEN = 1,
+ };
+
+ struct MatchRequest {
+ uint16_t method;
+ uint8_t fileid_valid;
+ uint32_t fileid;
+ int8_t is_bold;
+ int8_t is_italic;
+ uint8_t family_len;
+ // char family[0] follows.
+ };
+
+ struct MatchReply {
+ uint8_t result;
+ uint32_t result_fileid;
+ uint16_t filename_len;
+ // char filename[0] follows.
+ };
+
+ struct OpenRequest {
+ uint16_t method;
+ unsigned fileid;
+ };
+
+ struct OpenReply {
+ uint8_t result;
+ };
+
+ private:
+ const int fd_;
+};
+
+#endif // FontConfigIPC_DEFINED
diff --git a/skia/skia.gyp b/skia/skia.gyp
index 4158b2b..912e80a 100755
--- a/skia/skia.gyp
+++ b/skia/skia.gyp
@@ -358,7 +358,6 @@
'../third_party/skia/src/ports/SkFontHost_FreeType.cpp',
#'../third_party/skia/src/ports/SkFontHost_android.cpp',
#'../third_party/skia/src/ports/SkFontHost_ascender.cpp',
- '../third_party/skia/src/ports/SkFontHost_fontconfig.cpp',
'../third_party/skia/src/ports/SkFontHost_tables.cpp',
#'../third_party/skia/src/ports/SkFontHost_gamma.cpp',
'../third_party/skia/src/ports/SkFontHost_gamma_none.cpp',
@@ -566,7 +565,6 @@
'../third_party/skia/src/ports/SkFontHost_FreeType.cpp',
'../third_party/skia/src/ports/SkFontHost_TryeType_Tables.cpp',
'../third_party/skia/src/ports/SkFontHost_gamma_none.cpp',
- '../third_party/skia/src/ports/SkFontHost_fontconfig.cpp',
'../third_party/skia/src/ports/SkFontHost_gamma_none.cpp',
'../third_party/skia/src/ports/SkFontHost_tables.cpp',
'../third_party/skia/src/core/SkTypeface.cpp',
@@ -595,6 +593,12 @@
'../third_party/skia/src/ports/SkFontHost_none.cpp',
'ext/SkTypeface_fake.cpp',
],
+ 'sources': [
+ # http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+ 'ext/SkFontHost_fontconfig.cpp',
+ 'ext/SkFontHost_fontconfig_direct.cpp',
+ 'ext/SkFontHost_fontconfig_ipc.cpp',
+ ],
'export_dependent_settings': [
'../third_party/harfbuzz/harfbuzz.gyp:harfbuzz',
'../third_party/harfbuzz/harfbuzz.gyp:harfbuzz_interface',