1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
#include "base/file_util.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/scoped_ptr.h"
#include "base/shared_memory.h"
#include "chrome/common/font_loader_mac.h"
#include "chrome/common/sandbox_mac_unittest_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
using sandboxtest::MacSandboxTest;
using sandbox::Sandbox;
bool CGFontFromFontContainer(ATSFontContainerRef container, CGFontRef* out) {
// Count the number of fonts that were loaded.
ItemCount fontCount = 0;
OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0,
NULL, &fontCount);
if (err != noErr || fontCount < 1) {
return false;
}
// Load font from container.
ATSFontRef font_ref_ats = 0;
ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1,
&font_ref_ats, NULL);
if (!font_ref_ats) {
return false;
}
// Convert to cgFont.
CGFontRef font_ref_cg = CGFontCreateWithPlatformFont(&font_ref_ats);
if (!font_ref_cg) {
return false;
}
*out = font_ref_cg;
return true;
}
class ScopedFontContainer {
public:
explicit ScopedFontContainer(ATSFontContainerRef ref)
: container_ref(ref) {}
~ScopedFontContainer() {
ATSFontDeactivate(container_ref, NULL, kATSOptionFlagsDefault);
}
ATSFontContainerRef container_ref;
};
class FontLoadingTestCase : public sandboxtest::MacSandboxTestCase {
public:
FontLoadingTestCase() : font_data_length_(-1) {}
virtual bool BeforeSandboxInit();
virtual bool SandboxedTest();
private:
scoped_ptr<base::SharedMemory> font_shmem_;
size_t font_data_length_;
};
REGISTER_SANDBOX_TEST_CASE(FontLoadingTestCase);
// Load raw font data into shared memory object.
bool FontLoadingTestCase::BeforeSandboxInit() {
std::string font_data;
if (!file_util::ReadFileToString(FilePath(test_data_.c_str()), &font_data)) {
LOG(ERROR) << "Failed to read font data from file (" << test_data_ << ")";
return false;
}
font_data_length_ = font_data.length();
if (font_data_length_ <= 0) {
LOG(ERROR) << "No font data: " << font_data_length_;
return false;
}
font_shmem_.reset(new base::SharedMemory);
if (!font_shmem_.get()) {
LOG(ERROR) << "Failed to create shared memory object.";
return false;
}
if (!font_shmem_->CreateAndMapAnonymous(font_data_length_)) {
LOG(ERROR) << "SharedMemory::Create failed";
return false;
}
memcpy(font_shmem_->memory(), font_data.c_str(), font_data_length_);
if (!font_shmem_->Unmap()) {
LOG(ERROR) << "SharedMemory::Unmap failed";
return false;
}
return true;
}
bool FontLoadingTestCase::SandboxedTest() {
base::SharedMemoryHandle shmem_handle;
if (!font_shmem_->ShareToProcess(NULL, &shmem_handle)) {
LOG(ERROR) << "SharedMemory::ShareToProcess failed";
return false;
}
ATSFontContainerRef font_container;
if (!FontLoader::ATSFontContainerFromBuffer(shmem_handle, font_data_length_,
&font_container)) {
LOG(ERROR) << "Call to CreateCGFontFromBuffer() failed";
return false;
}
// Unload the font container when done.
ScopedFontContainer scoped_unloader(font_container);
CGFontRef cg_font_ref;
if (!CGFontFromFontContainer(font_container, &cg_font_ref)) {
LOG(ERROR) << "CGFontFromFontContainer failed";
return false;
}
if (!cg_font_ref) {
LOG(ERROR) << "Got NULL CGFontRef";
return false;
}
base::mac::ScopedCFTypeRef<CGFontRef> cgfont(cg_font_ref);
CTFontRef ct_font_ref =
CTFontCreateWithGraphicsFont(cgfont.get(), 16.0, NULL, NULL);
base::mac::ScopedCFTypeRef<CTFontRef> ctfont(ct_font_ref);
if (!ct_font_ref) {
LOG(ERROR) << "CTFontCreateWithGraphicsFont() failed";
return false;
}
// Do something with the font to make sure it's loaded.
CGFloat cap_height = CTFontGetCapHeight(ct_font_ref);
if (cap_height <= 0.0) {
LOG(ERROR) << "Got bad value for CTFontGetCapHeight " << cap_height;
return false;
}
return true;
}
TEST_F(MacSandboxTest, FontLoadingTest) {
FilePath temp_file_path;
FILE* temp_file = file_util::CreateAndOpenTemporaryFile(&temp_file_path);
ASSERT_TRUE(temp_file);
file_util::ScopedFILE temp_file_closer(temp_file);
base::SharedMemory font_data;
uint32 font_data_size;
NSFont* srcFont = [NSFont fontWithName:@"Geeza Pro" size:16.0];
EXPECT_TRUE(FontLoader::LoadFontIntoBuffer(srcFont,
&font_data, &font_data_size));
EXPECT_GT(font_data_size, 0U);
file_util::WriteFileDescriptor(fileno(temp_file),
static_cast<const char *>(font_data.memory()), font_data_size);
ASSERT_TRUE(RunTestInSandbox(Sandbox::SANDBOX_TYPE_RENDERER,
"FontLoadingTestCase", temp_file_path.value().c_str()));
temp_file_closer.reset();
ASSERT_TRUE(file_util::Delete(temp_file_path, false));
}
} // namespace
|