// 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 <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <unistd.h>
#include "base/debug/trace_event.h"
#include "base/files/file_util.h"
#include "base/pickle.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "skia/ext/refptr.h"
#include "skia/ext/skia_utils_base.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkStream.h"
namespace content {
// Return a stream from the file descriptor, or NULL on failure.
SkStream* StreamFromFD(int fd) {
skia::RefPtr<SkData> data = skia::AdoptRef(SkData::NewFromFD(fd));
if (!data) {
return NULL;
}
return new SkMemoryStream(data.get());
}
void CloseFD(int fd) {
int err = IGNORE_EINTR(close(fd));
DCHECK(!err);
}
FontConfigIPC::FontConfigIPC(int fd)
: fd_(fd) {
}
FontConfigIPC::~FontConfigIPC() {
CloseFD(fd_);
}
bool FontConfigIPC::matchFamilyName(const char familyName[],
SkTypeface::Style requestedStyle,
FontIdentity* outFontIdentity,
SkString* outFamilyName,
SkTypeface::Style* outStyle) {
TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::matchFamilyName");
size_t familyNameLen = familyName ? strlen(familyName) : 0;
if (familyNameLen > kMaxFontFamilyLength)
return false;
Pickle request;
request.WriteInt(METHOD_MATCH);
request.WriteData(familyName, familyNameLen);
request.WriteUInt32(requestedStyle);
uint8_t reply_buf[2048];
const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf,
sizeof(reply_buf), NULL,
request);
if (r == -1)
return false;
Pickle reply(reinterpret_cast<char*>(reply_buf), r);
PickleIterator iter(reply);
bool result;
if (!reply.ReadBool(&iter, &result))
return false;
if (!result)
return false;
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 (outFontIdentity)
*outFontIdentity = reply_identity;
if (outFamilyName)
*outFamilyName = reply_family;
if (outStyle)
*outStyle = static_cast<SkTypeface::Style>(reply_style);
return true;
}
SkStream* FontConfigIPC::openStream(const FontIdentity& identity) {
TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream");
Pickle request;
request.WriteInt(METHOD_OPEN);
request.WriteUInt32(identity.fID);
int result_fd = -1;
uint8_t reply_buf[256];
const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf,
sizeof(reply_buf),
&result_fd, request);
if (r == -1)
return NULL;
Pickle reply(reinterpret_cast<char*>(reply_buf), r);
bool result;
PickleIterator iter(reply);
if (!reply.ReadBool(&iter, &result) ||
!result) {
if (result_fd)
CloseFD(result_fd);
return NULL;
}
SkStream* stream = StreamFromFD(result_fd);
CloseFD(result_fd);
return stream;
}
} // namespace content