summaryrefslogtreecommitdiff
path: root/chromium/content/common/sandbox_mac_fontloading_unittest.mm
blob: db98aab9a0a72289dd2d8f2a4e2ec8eabb9ca76c (plain)
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
// Copyright (c) 2012 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 <stddef.h>

#include <memory>

#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/shared_memory.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/mac/font_loader.h"
#include "content/common/sandbox_mac_unittest_helper.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

class FontLoadingTestCase : public MacSandboxTestCase {
 public:
  FontLoadingTestCase() : font_data_length_(-1) {}
  bool BeforeSandboxInit() override;
  bool SandboxedTest() override;

 private:
  mojo::ScopedSharedBufferHandle 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 (!base::ReadFileToString(base::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_ = mojo::SharedBufferHandle::Create(font_data_length_);
  if (!font_shmem_.is_valid()) {
    LOG(ERROR) << "Failed to create shared memory object.";
    return false;
  }

  mojo::ScopedSharedBufferMapping mapping = font_shmem_->Map(font_data_length_);
  if (!mapping) {
    LOG(ERROR) << "ScopedSharedBufferHandle::Map failed";
    return false;
  }

  memcpy(mapping.get(), font_data.c_str(), font_data_length_);
  return true;
}

bool FontLoadingTestCase::SandboxedTest() {
  mojo::ScopedSharedBufferHandle shmem_handle =
      font_shmem_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY);
  if (!shmem_handle.is_valid()) {
    LOG(ERROR) << "ScopedSharedBufferHandle handle duplication failed";
    return false;
  }

  CGFontRef cg_font_ref;
  if (!FontLoader::CGFontRefFromBuffer(std::move(shmem_handle),
                                       font_data_length_, &cg_font_ref)) {
    LOG(ERROR) << "Call to CreateCGFontFromBuffer() failed";
    return false;
  }

  if (!cg_font_ref) {
    LOG(ERROR) << "Got NULL CGFontRef";
    return false;
  }
  base::ScopedCFTypeRef<CGFontRef> cgfont(cg_font_ref);

  CTFontRef ct_font_ref =
      CTFontCreateWithGraphicsFont(cgfont.get(), 16.0, NULL, NULL);
  base::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) {
  base::FilePath temp_file_path;
  FILE* temp_file = base::CreateAndOpenTemporaryFile(&temp_file_path);
  ASSERT_TRUE(temp_file);
  base::ScopedFILE temp_file_closer(temp_file);

  std::unique_ptr<FontLoader::ResultInternal> result =
      FontLoader::LoadFontForTesting(base::ASCIIToUTF16("Geeza Pro"), 16);
  EXPECT_GT(result->font_data_size, 0U);
  EXPECT_GT(result->font_id, 0U);

  mojo::ScopedSharedBufferMapping mapping =
      result->font_data->Map(result->font_data_size);
  ASSERT_TRUE(mapping);

  base::WriteFileDescriptor(fileno(temp_file),
                            static_cast<const char*>(mapping.get()),
                            result->font_data_size);

  ASSERT_TRUE(RunTestInSandbox(service_manager::SANDBOX_TYPE_RENDERER,
                               "FontLoadingTestCase",
                               temp_file_path.value().c_str()));
  temp_file_closer.reset();
  ASSERT_TRUE(base::DeleteFile(temp_file_path, false));
}

}  // namespace content