summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_common.gypi2
-rwxr-xr-xchrome/chrome_tests.gypi1
-rw-r--r--chrome/common/font_descriptor_mac.h32
-rw-r--r--chrome/common/font_descriptor_mac.mm20
-rw-r--r--chrome/common/font_descriptor_mac_unittest.mm91
-rw-r--r--chrome/common/font_loader_mac.h26
-rw-r--r--chrome/common/font_loader_mac.mm55
-rw-r--r--chrome/common/render_messages.h19
-rwxr-xr-xchrome/common/render_messages_internal.h10
-rw-r--r--chrome/common/sandbox_mac_fontloading_unittest.mm61
-rw-r--r--ipc/ipc_message_utils.h39
11 files changed, 293 insertions, 63 deletions
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 7be94dd..b491315 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -47,6 +47,8 @@
'common/debug_flags.h',
'common/devtools_messages.h',
'common/devtools_messages_internal.h',
+ 'common/font_descriptor_mac.h',
+ 'common/font_descriptor_mac.mm',
'common/geoposition.cc',
'common/geoposition.h',
'common/gpu_messages.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 31f31a5..19dc485 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1000,6 +1000,7 @@
'common/extensions/update_manifest_unittest.cc',
'common/extensions/url_pattern_unittest.cc',
'common/extensions/user_script_unittest.cc',
+ 'common/font_descriptor_mac_unittest.mm',
'common/important_file_writer_unittest.cc',
'common/json_pref_store_unittest.cc',
'common/json_value_serializer_unittest.cc',
diff --git a/chrome/common/font_descriptor_mac.h b/chrome/common/font_descriptor_mac.h
new file mode 100644
index 0000000..25ae9db
--- /dev/null
+++ b/chrome/common/font_descriptor_mac.h
@@ -0,0 +1,32 @@
+// 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.
+
+#ifndef CHROME_COMMON_FONT_DESCRIPTOR_MAC_H_
+#define CHROME_COMMON_FONT_DESCRIPTOR_MAC_H_
+
+#include "base/string16.h"
+
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
+// Container to allow serializing an NSFont over IPC.
+struct FontDescriptor {
+ explicit FontDescriptor(NSFont* font);
+
+ FontDescriptor() : font_point_size(0) {}
+
+ // Return an autoreleased NSFont corresponding to the font description.
+ NSFont* nsFont() const;
+
+ // Name of the font.
+ string16 font_name;
+
+ // Size in points.
+ float font_point_size;
+};
+
+#endif // CHROME_COMMON_FONT_DESCRIPTOR_MAC_H_
diff --git a/chrome/common/font_descriptor_mac.mm b/chrome/common/font_descriptor_mac.mm
new file mode 100644
index 0000000..485c215
--- /dev/null
+++ b/chrome/common/font_descriptor_mac.mm
@@ -0,0 +1,20 @@
+// 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.
+
+#include "chrome/common/font_descriptor_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/sys_string_conversions.h"
+
+FontDescriptor::FontDescriptor(NSFont* font) {
+ font_name = base::SysNSStringToUTF16([font fontName]);
+ font_point_size = [font pointSize];
+}
+
+NSFont* FontDescriptor::nsFont() const {
+ NSString* font_name_ns = base::SysUTF16ToNSString(font_name);
+ NSFont* font = [NSFont fontWithName:font_name_ns size:font_point_size];
+ return font;
+}
diff --git a/chrome/common/font_descriptor_mac_unittest.mm b/chrome/common/font_descriptor_mac_unittest.mm
new file mode 100644
index 0000000..442e8e2
--- /dev/null
+++ b/chrome/common/font_descriptor_mac_unittest.mm
@@ -0,0 +1,91 @@
+// 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.
+
+#include "chrome/common/font_descriptor_mac.h"
+
+#include <Cocoa/Cocoa.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+class FontSerializationTest : public PlatformTest {};
+
+
+// Compare 2 fonts, make sure they point at the same font definition and have
+// the same style. Only Bold & Italic style attributes are tested since those
+// are the only ones we care about at the moment.
+bool CompareFonts(NSFont* font1, NSFont* font2) {
+ ATSFontRef id1 = CTFontGetPlatformFont(reinterpret_cast<CTFontRef>(font1), 0);
+ ATSFontRef id2 = CTFontGetPlatformFont(reinterpret_cast<CTFontRef>(font2), 0);
+
+ if (id1 != id2) {
+ LOG(ERROR) << "ATSFontRefs for "
+ << [[font1 fontName] UTF8String]
+ << " and "
+ << [[font2 fontName] UTF8String]
+ << " are different";
+ return false;
+ }
+
+ CGFloat size1 = [font1 pointSize];
+ CGFloat size2 = [font2 pointSize];
+ if (size1 != size2) {
+ LOG(ERROR) << "font sizes for "
+ << [[font1 fontName] UTF8String] << " (" << size1 << ")"
+ << "and"
+ << [[font2 fontName] UTF8String] << " (" << size2 << ")"
+ << " are different";
+ return false;
+ }
+
+ NSFontTraitMask traits1 = [[NSFontManager sharedFontManager]
+ traitsOfFont:font1];
+ NSFontTraitMask traits2 = [[NSFontManager sharedFontManager]
+ traitsOfFont:font2];
+
+ bool is_bold1 = traits1 & NSBoldFontMask;
+ bool is_bold2 = traits2 & NSBoldFontMask;
+ bool is_italic1 = traits1 & NSItalicFontMask;
+ bool is_italic2 = traits2 & NSItalicFontMask;
+
+ if (is_bold1 != is_bold2 || is_italic1 != is_italic2) {
+ LOG(ERROR) << "Style information for "
+ << [[font1 fontName] UTF8String]
+ << " and "
+ << [[font2 fontName] UTF8String]
+ << " are different";
+ return false;
+ }
+
+ return true;
+}
+
+// Verify that serialization and deserialization of fonts with various styles
+// is performed correctly by FontDescriptor.
+TEST_F(FontSerializationTest, StyledFonts) {
+ NSFont* plain_font = [NSFont systemFontOfSize:12.0];
+ ASSERT_TRUE(plain_font != nil);
+ FontDescriptor desc_plain(plain_font);
+ EXPECT_TRUE(CompareFonts(plain_font, desc_plain.nsFont()));
+
+ NSFont* bold_font = [NSFont boldSystemFontOfSize:30.0];
+ ASSERT_TRUE(bold_font != nil);
+ FontDescriptor desc_bold(bold_font);
+ EXPECT_TRUE(CompareFonts(bold_font, desc_bold.nsFont()));
+
+ NSFont* italic_bold_font =
+ [[NSFontManager sharedFontManager]
+ fontWithFamily:@"Courier"
+ traits:(NSBoldFontMask | NSItalicFontMask)
+ weight:5
+ size:18.0];
+ ASSERT_TRUE(italic_bold_font != nil);
+ FontDescriptor desc_italic_bold(italic_bold_font);
+ EXPECT_TRUE(CompareFonts(italic_bold_font, desc_italic_bold.nsFont()));
+}
+
+} // namsepace
diff --git a/chrome/common/font_loader_mac.h b/chrome/common/font_loader_mac.h
index 8d2467f..2ec42bce 100644
--- a/chrome/common/font_loader_mac.h
+++ b/chrome/common/font_loader_mac.h
@@ -10,6 +10,12 @@
#include "base/shared_memory.h"
#include "base/string16.h"
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
// Provides functionality to transmit fonts over IPC.
//
// Note about font formats: .dfont (datafork suitcase) fonts are currently not
@@ -18,32 +24,32 @@
class FontLoader {
public:
- // Load a font specified by |font_name| and |font_point_size| into a shared
- // memory buffer suitable for sending over IPC.
+ // Load a font specified by |font_to_encode| into a shared memory buffer
+ // suitable for sending over IPC.
//
// On return:
// returns true on success, false on failure.
// |font_data| - shared memory buffer containing the raw data for the font
// file.
// |font_data_size| - size of data contained in |font_data|.
- static bool LoadFontIntoBuffer(const string16& font_name,
- float font_point_size,
+ static bool LoadFontIntoBuffer(NSFont* font_to_encode,
base::SharedMemory* font_data,
uint32* font_data_size);
// Given a shared memory buffer containing the raw data for a font file, load
- // the font into a CGFontRef.
+ // the font and return a container ref.
//
// |data| - A shared memory handle pointing to the raw data from a font file.
// |data_size| - Size of |data|.
//
// On return:
// returns true on success, false on failure.
- // |font| - A CGFontRef containing the designated font, the caller is
- // responsible for releasing this value.
- static bool CreateCGFontFromBuffer(base::SharedMemoryHandle font_data,
- uint32 font_data_size,
- CGFontRef* font);
+ // |font_container| - A font container corresponding to the designated font.
+ // The caller is responsible for releasing this value via ATSFontDeactivate()
+ // when done
+ static bool ATSFontContainerFromBuffer(base::SharedMemoryHandle font_data,
+ uint32 font_data_size,
+ ATSFontContainerRef* font_container);
};
#endif // CHROME_COMMON_FONT_LOADER_MAC_H_
diff --git a/chrome/common/font_loader_mac.mm b/chrome/common/font_loader_mac.mm
index a6b9c25..849ae87 100644
--- a/chrome/common/font_loader_mac.mm
+++ b/chrome/common/font_loader_mac.mm
@@ -15,17 +15,16 @@
#include "base/sys_string_conversions.h"
// static
-bool FontLoader::LoadFontIntoBuffer(const string16& font_name,
- float font_point_size,
+bool FontLoader::LoadFontIntoBuffer(NSFont* font_to_encode,
base::SharedMemory* font_data,
uint32* font_data_size) {
CHECK(font_data && font_data_size);
*font_data_size = 0;
+ // Used only for logging.
+ std::string font_name([[font_to_encode fontName] UTF8String]);
+
// Load appropriate NSFont.
- NSString* font_name_ns = base::SysUTF16ToNSString(font_name);
- NSFont* font_to_encode =
- [NSFont fontWithName:font_name_ns size:font_point_size];
if (!font_to_encode) {
LOG(ERROR) << "Failed to load font " << font_name;
return false;
@@ -90,9 +89,12 @@ bool FontLoader::LoadFontIntoBuffer(const string16& font_name,
}
// static
-bool FontLoader::CreateCGFontFromBuffer(base::SharedMemoryHandle font_data,
- uint32 font_data_size,
- CGFontRef *font) {
+bool FontLoader::ATSFontContainerFromBuffer(base::SharedMemoryHandle font_data,
+ uint32 font_data_size,
+ ATSFontContainerRef* font_container)
+{
+ CHECK(font_container);
+
using base::SharedMemory;
DCHECK(SharedMemory::IsHandleValid(font_data));
DCHECK_GT(font_data_size, 0U);
@@ -101,41 +103,14 @@ bool FontLoader::CreateCGFontFromBuffer(base::SharedMemoryHandle font_data,
if (!shm.Map(font_data_size))
return false;
- ATSFontContainerRef font_container = 0;
+ // A value of 3 means the font is private and can't be seen by anyone else.
+ // This is the value used by WebKit when activating remote fonts.
+ const ATSFontContext kFontContextPrivate = 3;
OSStatus err = ATSFontActivateFromMemory(shm.memory(), font_data_size,
- kATSFontContextLocal, kATSFontFormatUnspecified,
- NULL, kATSOptionFlagsDefault, &font_container );
+ kFontContextPrivate, kATSFontFormatUnspecified, NULL,
+ kATSOptionFlagsDefault, font_container);
if (err != noErr || !font_container)
return false;
- // Count the number of fonts that were loaded.
- ItemCount fontCount = 0;
- err = ATSFontFindFromContainer(font_container, kATSOptionFlagsDefault, 0,
- NULL, &fontCount);
-
- if (err != noErr || fontCount < 1) {
- ATSFontDeactivate(font_container, NULL, kATSOptionFlagsDefault);
- return false;
- }
-
- // Load font from container.
- ATSFontRef font_ref_ats = 0;
- ATSFontFindFromContainer(font_container, kATSOptionFlagsDefault, 1,
- &font_ref_ats, NULL);
-
- if (!font_ref_ats) {
- ATSFontDeactivate(font_container, NULL, kATSOptionFlagsDefault);
- return false;
- }
-
- // Convert to cgFont.
- CGFontRef font_ref_cg = CGFontCreateWithPlatformFont(&font_ref_ats);
-
- if (!font_ref_cg) {
- ATSFontDeactivate(font_container, NULL, kATSOptionFlagsDefault);
- return false;
- }
-
- *font = font_ref_cg;
return true;
}
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index e501a8b9..f5a3376 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -22,6 +22,7 @@
#include "chrome/common/edit_command.h"
#include "chrome/common/extensions/extension_extent.h"
#include "chrome/common/extensions/url_pattern.h"
+#include "chrome/common/font_descriptor_mac.h"
#include "chrome/common/navigation_gesture.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/common/renderer_preferences.h"
@@ -914,6 +915,24 @@ struct ParamTraits<webkit_glue::FormField> {
}
};
+// Traits for FontDescriptor structure to pack/unpack.
+template <>
+struct ParamTraits<FontDescriptor> {
+ typedef FontDescriptor param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.font_name);
+ WriteParam(m, p.font_point_size);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return(
+ ReadParam(m, iter, &p->font_name) &&
+ ReadParam(m, iter, &p->font_point_size));
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<FontDescriptor>");
+ }
+};
+
// Traits for ViewHostMsg_FrameNavigate_Params structure to pack/unpack.
template <>
struct ParamTraits<ViewHostMsg_FrameNavigate_Params> {
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 4596986..7d38c3a 100755
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -39,6 +39,10 @@
#include "base/file_descriptor_posix.h"
#endif
+#if defined(OS_MACOSX)
+#include "chrome/common/font_descriptor_mac.h"
+#endif
+
// TODO(mpcomplete): rename ViewMsg and ViewHostMsg to something that makes
// more sense with our current design.
@@ -1433,6 +1437,12 @@ IPC_BEGIN_MESSAGES(ViewHost)
#if defined(OS_MACOSX)
IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardFindPboardWriteStringAsync,
string16 /* text */)
+
+ // Request that the browser load a font into shared memory for us.
+ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_LoadFont,
+ FontDescriptor /* font to load */,
+ uint32 /* buffer size */,
+ base::SharedMemoryHandle /* font data */)
#endif
#if defined(OS_WIN)
diff --git a/chrome/common/sandbox_mac_fontloading_unittest.mm b/chrome/common/sandbox_mac_fontloading_unittest.mm
index 9eadf0d..a20d263 100644
--- a/chrome/common/sandbox_mac_fontloading_unittest.mm
+++ b/chrome/common/sandbox_mac_fontloading_unittest.mm
@@ -17,6 +17,48 @@ namespace {
using sandboxtest::MacSandboxTest;
+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) {}
@@ -74,19 +116,27 @@ bool FontLoadingTestCase::SandboxedTest() {
return false;
}
- CGFontRef font_ref;
- if (!FontLoader::CreateCGFontFromBuffer(shmem_handle, font_data_length_,
- &font_ref)) {
+ ATSFontContainerRef font_container;
+ if (!FontLoader::ATSFontContainerFromBuffer(shmem_handle, font_data_length_,
+ &font_container)) {
LOG(ERROR) << "Call to CreateCGFontFromBuffer() failed";
return false;
}
- scoped_cftyperef<CGFontRef> cgfont;
+ // Unload the font container when done.
+ ScopedFontContainer scoped_unloader(font_container);
+
+ CGFontRef font_ref;
+ if (!CGFontFromFontContainer(font_container, &font_ref)) {
+ LOG(ERROR) << "CGFontFromFontContainer failed";
+ return false;
+ }
if (!font_ref) {
LOG(ERROR) << "Got NULL CGFontRef";
return false;
}
+ scoped_cftyperef<CGFontRef> cgfont;
cgfont.reset(font_ref);
const NSFont* nsfont = reinterpret_cast<const NSFont*>(
@@ -116,7 +166,8 @@ TEST_F(MacSandboxTest, FontLoadingTest) {
base::SharedMemory font_data;
uint32 font_data_size;
- EXPECT_TRUE(FontLoader::LoadFontIntoBuffer(ASCIIToUTF16("Geeza Pro"), 16.0,
+ 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);
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index df2c6c7..46c7298 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -226,6 +226,31 @@ struct ParamTraits<unsigned long long> {
}
};
+// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
+// should be sure to check the sanity of these values after receiving them over
+// IPC.
+template <>
+struct ParamTraits<float> {
+ typedef float param_type;
+ static void Write(Message* m, const param_type& p) {
+ m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
+ }
+ static bool Read(const Message* m, void** iter, param_type* r) {
+ const char *data;
+ int data_size;
+ if (!m->ReadData(iter, &data, &data_size) ||
+ data_size != sizeof(param_type)) {
+ NOTREACHED();
+ return false;
+ }
+ memcpy(r, data, sizeof(param_type));
+ return true;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(StringPrintf(L"e", p));
+ }
+};
+
template <>
struct ParamTraits<double> {
typedef double param_type;
@@ -234,16 +259,14 @@ struct ParamTraits<double> {
}
static bool Read(const Message* m, void** iter, param_type* r) {
const char *data;
- int data_size = 0;
- bool result = m->ReadData(iter, &data, &data_size);
- if (result && data_size == sizeof(param_type)) {
- memcpy(r, data, sizeof(param_type));
- } else {
- result = false;
+ int data_size;
+ if (!m->ReadData(iter, &data, &data_size) ||
+ data_size != sizeof(param_type)) {
NOTREACHED();
+ return false;
}
-
- return result;
+ memcpy(r, data, sizeof(param_type));
+ return true;
}
static void Log(const param_type& p, std::wstring* l) {
l->append(StringPrintf(L"e", p));