diff options
Diffstat (limited to 'skia/ext/SkFontHost_fontconfig_ipc.cpp')
-rw-r--r-- | skia/ext/SkFontHost_fontconfig_ipc.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
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; +} |