Home | History | Annotate | Download | only in common
      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