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
, 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
= base::UnixDomainSocket::SendRecvMsg(
100 fd_
, reply_buf
, sizeof(reply_buf
), NULL
, request
);
104 base::Pickle
reply(reinterpret_cast<char*>(reply_buf
), r
);
105 base::PickleIterator
iter(reply
);
107 if (!iter
.ReadBool(&result
))
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
)) {
122 *outFontIdentity
= reply_identity
;
124 *outFamilyName
= reply_family
;
126 *outStyle
= static_cast<SkTypeface::Style
>(reply_style
);
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
);
146 uint8_t reply_buf
[256];
147 const ssize_t r
= base::UnixDomainSocket::SendRecvMsg(
148 fd_
, reply_buf
, sizeof(reply_buf
), &result_fd
, request
);
152 base::Pickle
reply(reinterpret_cast<char*>(reply_buf
), r
);
154 base::PickleIterator
iter(reply
);
155 if (!iter
.ReadBool(&result
) || !result
) {
161 scoped_refptr
<MappedFontFile
> mapped_font_file
=
162 new MappedFontFile(identity
.fID
);
163 if (!mapped_font_file
->Initialize(result_fd
))
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