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"
10 #include <sys/socket.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"
30 class FontConfigIPC::MappedFontFile
31 : public base::RefCountedThreadSafe
<MappedFontFile
> {
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));
50 return new SkMemoryStream(data
.get());
54 friend class base::RefCountedThreadSafe
<MappedFontFile
>;
57 auto font_config
= static_cast<FontConfigIPC
*>(FontConfigIPC::RefGlobal());
58 font_config
->RemoveMappedFontFile(this);
61 static void ReleaseProc(const void* ptr
, size_t length
, void* context
) {
62 base::ThreadRestrictions::ScopedAllowIO allow_munmap
;
63 static_cast<MappedFontFile
*>(context
)->Release();
67 base::MemoryMappedFile mapped_font_file_
;
70 void CloseFD(int fd
) {
71 int err
= IGNORE_EINTR(close(fd
));
75 FontConfigIPC::FontConfigIPC(int fd
)
79 FontConfigIPC::~FontConfigIPC() {
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
)
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
= UnixDomainSocket::SendRecvMsg(fd_
, reply_buf
,
100 sizeof(reply_buf
), NULL
,
105 Pickle
reply(reinterpret_cast<char*>(reply_buf
), r
);
106 PickleIterator
iter(reply
);
108 if (!iter
.ReadBool(&result
))
113 SkString reply_family
;
114 FontIdentity reply_identity
;
115 uint32_t reply_style
;
116 if (!skia::ReadSkString(&iter
, &reply_family
) ||
117 !skia::ReadSkFontIdentity(&iter
, &reply_identity
) ||
118 !iter
.ReadUInt32(&reply_style
)) {
123 *outFontIdentity
= reply_identity
;
125 *outFamilyName
= reply_family
;
127 *outStyle
= static_cast<SkTypeface::Style
>(reply_style
);
132 SkStreamAsset
* FontConfigIPC::openStream(const FontIdentity
& identity
) {
133 TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream");
136 base::AutoLock
lock(lock_
);
137 auto mapped_font_files_it
= mapped_font_files_
.find(identity
.fID
);
138 if (mapped_font_files_it
!= mapped_font_files_
.end())
139 return mapped_font_files_it
->second
->CreateMemoryStream();
143 request
.WriteInt(METHOD_OPEN
);
144 request
.WriteUInt32(identity
.fID
);
147 uint8_t reply_buf
[256];
148 const ssize_t r
= UnixDomainSocket::SendRecvMsg(fd_
, reply_buf
,
150 &result_fd
, request
);
155 Pickle
reply(reinterpret_cast<char*>(reply_buf
), r
);
157 PickleIterator
iter(reply
);
158 if (!iter
.ReadBool(&result
) || !result
) {
164 scoped_refptr
<MappedFontFile
> mapped_font_file
=
165 new MappedFontFile(identity
.fID
);
166 if (!mapped_font_file
->Initialize(result_fd
))
170 base::AutoLock
lock(lock_
);
171 auto mapped_font_files_it
=
172 mapped_font_files_
.insert(std::make_pair(mapped_font_file
->font_id(),
173 mapped_font_file
.get())).first
;
174 return mapped_font_files_it
->second
->CreateMemoryStream();
178 void FontConfigIPC::RemoveMappedFontFile(MappedFontFile
* mapped_font_file
) {
179 base::AutoLock
lock(lock_
);
180 mapped_font_files_
.erase(mapped_font_file
->font_id());
183 } // namespace content