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 #import <Cocoa/Cocoa.h> 6 7 #include "base/file_util.h" 8 #include "base/logging.h" 9 #include "base/mac/scoped_cftyperef.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/shared_memory.h" 12 #include "content/common/mac/font_descriptor.h" 13 #include "content/common/mac/font_loader.h" 14 #include "content/common/sandbox_mac_unittest_helper.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace content { 18 19 class FontLoadingTestCase : public MacSandboxTestCase { 20 public: 21 FontLoadingTestCase() : font_data_length_(-1) {} 22 virtual bool BeforeSandboxInit() OVERRIDE; 23 virtual bool SandboxedTest() OVERRIDE; 24 private: 25 scoped_ptr<base::SharedMemory> font_shmem_; 26 size_t font_data_length_; 27 }; 28 REGISTER_SANDBOX_TEST_CASE(FontLoadingTestCase); 29 30 31 // Load raw font data into shared memory object. 32 bool FontLoadingTestCase::BeforeSandboxInit() { 33 std::string font_data; 34 if (!base::ReadFileToString(base::FilePath(test_data_.c_str()), &font_data)) { 35 LOG(ERROR) << "Failed to read font data from file (" << test_data_ << ")"; 36 return false; 37 } 38 39 font_data_length_ = font_data.length(); 40 if (font_data_length_ <= 0) { 41 LOG(ERROR) << "No font data: " << font_data_length_; 42 return false; 43 } 44 45 font_shmem_.reset(new base::SharedMemory); 46 if (!font_shmem_) { 47 LOG(ERROR) << "Failed to create shared memory object."; 48 return false; 49 } 50 51 if (!font_shmem_->CreateAndMapAnonymous(font_data_length_)) { 52 LOG(ERROR) << "SharedMemory::Create failed"; 53 return false; 54 } 55 56 memcpy(font_shmem_->memory(), font_data.c_str(), font_data_length_); 57 if (!font_shmem_->Unmap()) { 58 LOG(ERROR) << "SharedMemory::Unmap failed"; 59 return false; 60 } 61 return true; 62 } 63 64 bool FontLoadingTestCase::SandboxedTest() { 65 base::SharedMemoryHandle shmem_handle; 66 if (!font_shmem_->ShareToProcess(base::kNullProcessHandle, &shmem_handle)) { 67 LOG(ERROR) << "SharedMemory::ShareToProcess failed"; 68 return false; 69 } 70 71 CGFontRef cg_font_ref; 72 if (!FontLoader::CGFontRefFromBuffer(shmem_handle, font_data_length_, 73 &cg_font_ref)) { 74 LOG(ERROR) << "Call to CreateCGFontFromBuffer() failed"; 75 return false; 76 } 77 78 if (!cg_font_ref) { 79 LOG(ERROR) << "Got NULL CGFontRef"; 80 return false; 81 } 82 base::ScopedCFTypeRef<CGFontRef> cgfont(cg_font_ref); 83 84 CTFontRef ct_font_ref = 85 CTFontCreateWithGraphicsFont(cgfont.get(), 16.0, NULL, NULL); 86 base::ScopedCFTypeRef<CTFontRef> ctfont(ct_font_ref); 87 88 if (!ct_font_ref) { 89 LOG(ERROR) << "CTFontCreateWithGraphicsFont() failed"; 90 return false; 91 } 92 93 // Do something with the font to make sure it's loaded. 94 CGFloat cap_height = CTFontGetCapHeight(ct_font_ref); 95 96 if (cap_height <= 0.0) { 97 LOG(ERROR) << "Got bad value for CTFontGetCapHeight " << cap_height; 98 return false; 99 } 100 101 return true; 102 } 103 104 TEST_F(MacSandboxTest, FontLoadingTest) { 105 base::FilePath temp_file_path; 106 FILE* temp_file = base::CreateAndOpenTemporaryFile(&temp_file_path); 107 ASSERT_TRUE(temp_file); 108 file_util::ScopedFILE temp_file_closer(temp_file); 109 110 NSFont* srcFont = [NSFont fontWithName:@"Geeza Pro" size:16.0]; 111 FontDescriptor descriptor(srcFont); 112 FontLoader::Result result; 113 FontLoader::LoadFont(descriptor, &result); 114 EXPECT_GT(result.font_data_size, 0U); 115 EXPECT_GT(result.font_id, 0U); 116 117 file_util::WriteFileDescriptor(fileno(temp_file), 118 static_cast<const char *>(result.font_data.memory()), 119 result.font_data_size); 120 121 ASSERT_TRUE(RunTestInSandbox(SANDBOX_TYPE_RENDERER, 122 "FontLoadingTestCase", temp_file_path.value().c_str())); 123 temp_file_closer.reset(); 124 ASSERT_TRUE(base::DeleteFile(temp_file_path, false)); 125 } 126 127 } // namespace content 128