Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / common / font_config_ipc_linux.cc
blob7c0066dbc7ba67e68135a8f248aa63810910d6ca
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.
5 #include "content/common/font_config_ipc_linux.h"
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>
15 #include "base/files/file_util.h"
16 #include "base/files/memory_mapped_file.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/pickle.h"
19 #include "base/posix/unix_domain_socket_linux.h"
20 #include "base/threading/thread_restrictions.h"
21 #include "base/trace_event/trace_event.h"
22 #include "skia/ext/refptr.h"
23 #include "skia/ext/skia_utils_base.h"
24 #include "third_party/skia/include/core/SkData.h"
25 #include "third_party/skia/include/core/SkStream.h"
26 #include "third_party/skia/include/core/SkTypeface.h"
28 namespace content {
30 class FontConfigIPC::MappedFontFile
31 : public base::RefCountedThreadSafe<MappedFontFile> {
32 public:
33 explicit MappedFontFile(uint32_t font_id) : font_id_(font_id) {}
35 uint32_t font_id() const { return font_id_; }
37 bool Initialize(int fd) {
38 base::ThreadRestrictions::ScopedAllowIO allow_mmap;
39 return mapped_font_file_.Initialize(base::File(fd));
42 SkMemoryStream* CreateMemoryStream() {
43 DCHECK(mapped_font_file_.IsValid());
44 auto data = skia::AdoptRef(SkData::NewWithProc(
45 mapped_font_file_.data(), mapped_font_file_.length(),
46 &MappedFontFile::ReleaseProc, this));
47 if (!data)
48 return nullptr;
49 AddRef();
50 return new SkMemoryStream(data.get());
53 private:
54 friend class base::RefCountedThreadSafe<MappedFontFile>;
56 ~MappedFontFile() {
57 auto font_config = static_cast<FontConfigIPC*>(FontConfigIPC::RefGlobal());
58 font_config->RemoveMappedFontFile(this);
61 static void ReleaseProc(const void* ptr, void* context) {
62 base::ThreadRestrictions::ScopedAllowIO allow_munmap;
63 static_cast<MappedFontFile*>(context)->Release();
66 uint32_t font_id_;
67 base::MemoryMappedFile mapped_font_file_;
70 void CloseFD(int fd) {
71 int err = IGNORE_EINTR(close(fd));
72 DCHECK(!err);
75 FontConfigIPC::FontConfigIPC(int fd)
76 : fd_(fd) {
79 FontConfigIPC::~FontConfigIPC() {
80 CloseFD(fd_);
83 bool FontConfigIPC::matchFamilyName(const char familyName[],
84 SkTypeface::Style requestedStyle,
85 FontIdentity* outFontIdentity,
86 SkString* outFamilyName,
87 SkTypeface::Style* outStyle) {
88 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::matchFamilyName");
89 size_t familyNameLen = familyName ? strlen(familyName) : 0;
90 if (familyNameLen > kMaxFontFamilyLength)
91 return false;
93 base::Pickle request;
94 request.WriteInt(METHOD_MATCH);
95 request.WriteData(familyName, familyNameLen);
96 request.WriteUInt32(requestedStyle);
98 uint8_t reply_buf[2048];
99 const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
100 fd_, reply_buf, sizeof(reply_buf), NULL, request);
101 if (r == -1)
102 return false;
104 base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
105 base::PickleIterator iter(reply);
106 bool result;
107 if (!iter.ReadBool(&result))
108 return false;
109 if (!result)
110 return false;
112 SkString reply_family;
113 FontIdentity reply_identity;
114 uint32_t reply_style;
115 if (!skia::ReadSkString(&iter, &reply_family) ||
116 !skia::ReadSkFontIdentity(&iter, &reply_identity) ||
117 !iter.ReadUInt32(&reply_style)) {
118 return false;
121 if (outFontIdentity)
122 *outFontIdentity = reply_identity;
123 if (outFamilyName)
124 *outFamilyName = reply_family;
125 if (outStyle)
126 *outStyle = static_cast<SkTypeface::Style>(reply_style);
128 return true;
131 SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) {
132 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream");
135 base::AutoLock lock(lock_);
136 auto mapped_font_files_it = mapped_font_files_.find(identity.fID);
137 if (mapped_font_files_it != mapped_font_files_.end())
138 return mapped_font_files_it->second->CreateMemoryStream();
141 base::Pickle request;
142 request.WriteInt(METHOD_OPEN);
143 request.WriteUInt32(identity.fID);
145 int result_fd = -1;
146 uint8_t reply_buf[256];
147 const ssize_t r = base::UnixDomainSocket::SendRecvMsg(
148 fd_, reply_buf, sizeof(reply_buf), &result_fd, request);
149 if (r == -1)
150 return NULL;
152 base::Pickle reply(reinterpret_cast<char*>(reply_buf), r);
153 bool result;
154 base::PickleIterator iter(reply);
155 if (!iter.ReadBool(&result) || !result) {
156 if (result_fd)
157 CloseFD(result_fd);
158 return NULL;
161 scoped_refptr<MappedFontFile> mapped_font_file =
162 new MappedFontFile(identity.fID);
163 if (!mapped_font_file->Initialize(result_fd))
164 return nullptr;
167 base::AutoLock lock(lock_);
168 auto mapped_font_files_it =
169 mapped_font_files_.insert(std::make_pair(mapped_font_file->font_id(),
170 mapped_font_file.get())).first;
171 return mapped_font_files_it->second->CreateMemoryStream();
175 void FontConfigIPC::RemoveMappedFontFile(MappedFontFile* mapped_font_file) {
176 base::AutoLock lock(lock_);
177 mapped_font_files_.erase(mapped_font_file->font_id());
180 } // namespace content