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