1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/common/font_config_ipc_linux.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <sys/mman.h> 10 #include <sys/socket.h> 11 #include <sys/stat.h> 12 #include <sys/uio.h> 13 #include <unistd.h> 14 15 #include "base/debug/trace_event.h" 16 #include "base/files/file_util.h" 17 #include "base/pickle.h" 18 #include "base/posix/unix_domain_socket_linux.h" 19 #include "skia/ext/refptr.h" 20 #include "skia/ext/skia_utils_base.h" 21 #include "third_party/skia/include/core/SkData.h" 22 #include "third_party/skia/include/core/SkStream.h" 23 24 namespace content { 25 26 // Return a stream from the file descriptor, or NULL on failure. 27 SkStream* StreamFromFD(int fd) { 28 skia::RefPtr<SkData> data = skia::AdoptRef(SkData::NewFromFD(fd)); 29 if (!data) { 30 return NULL; 31 } 32 return new SkMemoryStream(data.get()); 33 } 34 35 void CloseFD(int fd) { 36 int err = IGNORE_EINTR(close(fd)); 37 DCHECK(!err); 38 } 39 40 FontConfigIPC::FontConfigIPC(int fd) 41 : fd_(fd) { 42 } 43 44 FontConfigIPC::~FontConfigIPC() { 45 CloseFD(fd_); 46 } 47 48 bool FontConfigIPC::matchFamilyName(const char familyName[], 49 SkTypeface::Style requestedStyle, 50 FontIdentity* outFontIdentity, 51 SkString* outFamilyName, 52 SkTypeface::Style* outStyle) { 53 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::matchFamilyName"); 54 size_t familyNameLen = familyName ? strlen(familyName) : 0; 55 if (familyNameLen > kMaxFontFamilyLength) 56 return false; 57 58 Pickle request; 59 request.WriteInt(METHOD_MATCH); 60 request.WriteData(familyName, familyNameLen); 61 request.WriteUInt32(requestedStyle); 62 63 uint8_t reply_buf[2048]; 64 const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf, 65 sizeof(reply_buf), NULL, 66 request); 67 if (r == -1) 68 return false; 69 70 Pickle reply(reinterpret_cast<char*>(reply_buf), r); 71 PickleIterator iter(reply); 72 bool result; 73 if (!reply.ReadBool(&iter, &result)) 74 return false; 75 if (!result) 76 return false; 77 78 SkString reply_family; 79 FontIdentity reply_identity; 80 uint32_t reply_style; 81 if (!skia::ReadSkString(reply, &iter, &reply_family) || 82 !skia::ReadSkFontIdentity(reply, &iter, &reply_identity) || 83 !reply.ReadUInt32(&iter, &reply_style)) { 84 return false; 85 } 86 87 if (outFontIdentity) 88 *outFontIdentity = reply_identity; 89 if (outFamilyName) 90 *outFamilyName = reply_family; 91 if (outStyle) 92 *outStyle = static_cast<SkTypeface::Style>(reply_style); 93 94 return true; 95 } 96 97 SkStream* FontConfigIPC::openStream(const FontIdentity& identity) { 98 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream"); 99 Pickle request; 100 request.WriteInt(METHOD_OPEN); 101 request.WriteUInt32(identity.fID); 102 103 int result_fd = -1; 104 uint8_t reply_buf[256]; 105 const ssize_t r = UnixDomainSocket::SendRecvMsg(fd_, reply_buf, 106 sizeof(reply_buf), 107 &result_fd, request); 108 109 if (r == -1) 110 return NULL; 111 112 Pickle reply(reinterpret_cast<char*>(reply_buf), r); 113 bool result; 114 PickleIterator iter(reply); 115 if (!reply.ReadBool(&iter, &result) || 116 !result) { 117 if (result_fd) 118 CloseFD(result_fd); 119 return NULL; 120 } 121 122 SkStream* stream = StreamFromFD(result_fd); 123 CloseFD(result_fd); 124 return stream; 125 } 126 127 } // namespace content 128 129