Commit d7e0d173 authored by Olivier Yiptong's avatar Olivier Yiptong Committed by Commit Bot

FontAccess: Browser-side Mac enumeration

This change implements Mac font enumeration browser-side.

The current implementation is located in blink, cached in FontCache.
This browser-side implementation makes the Mac platform in-line with all
the other platform implementations.

A subsequent changelist removes the blink implementation altogether.

Bug: 1043306
Change-Id: Ic6dff854a74d27ad6d3df9d2ef3eb5217e3e55ff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410594
Commit-Queue: Olivier Yiptong <oyiptong@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarJoshua Bell <jsbell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808024}
parent 85707783
...@@ -896,6 +896,8 @@ source_set("browser") { ...@@ -896,6 +896,8 @@ source_set("browser") {
"font_access/font_access_manager_impl.h", "font_access/font_access_manager_impl.h",
"font_access/font_enumeration_cache.cc", "font_access/font_enumeration_cache.cc",
"font_access/font_enumeration_cache.h", "font_access/font_enumeration_cache.h",
"font_access/font_enumeration_cache_mac.h",
"font_access/font_enumeration_cache_mac.mm",
"font_access/font_enumeration_cache_win.cc", "font_access/font_enumeration_cache_win.cc",
"font_access/font_enumeration_cache_win.h", "font_access/font_enumeration_cache_win.h",
"font_list_async.cc", "font_list_async.cc",
......
...@@ -78,7 +78,8 @@ void FontAccessManagerImpl::EnumerateLocalFonts( ...@@ -78,7 +78,8 @@ void FontAccessManagerImpl::EnumerateLocalFonts(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_MAC)
const BindingContext& context = receivers_.current_context(); const BindingContext& context = receivers_.current_context();
RenderFrameHost* rfh = RenderFrameHost::FromID(context.frame_id); RenderFrameHost* rfh = RenderFrameHost::FromID(context.frame_id);
...@@ -126,7 +127,8 @@ void FontAccessManagerImpl::DidRequestPermission( ...@@ -126,7 +127,8 @@ void FontAccessManagerImpl::DidRequestPermission(
// Per-platform delegation for obtaining cached font enumeration data occurs // Per-platform delegation for obtaining cached font enumeration data occurs
// here, after the permission has been granted. // here, after the permission has been granted.
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_MAC)
ipc_task_runner_->PostTask( ipc_task_runner_->PostTask(
FROM_HERE, base::BindOnce( FROM_HERE, base::BindOnce(
[](EnumerateLocalFontsCallback callback, [](EnumerateLocalFontsCallback callback,
......
...@@ -79,10 +79,8 @@ class FontAccessManagerImplTest : public RenderViewHostImplTestHarness { ...@@ -79,10 +79,8 @@ class FontAccessManagerImplTest : public RenderViewHostImplTestHarness {
} }
void SetUp() override { void SetUp() override {
#if !defined(OS_MAC)
FontEnumerationCache* instance = FontEnumerationCache::GetInstance(); FontEnumerationCache* instance = FontEnumerationCache::GetInstance();
instance->ResetStateForTesting(); instance->ResetStateForTesting();
#endif
RenderViewHostImplTestHarness::SetUp(); RenderViewHostImplTestHarness::SetUp();
NavigateAndCommit(kTestUrl); NavigateAndCommit(kTestUrl);
...@@ -235,7 +233,8 @@ TEST_F(FontAccessManagerImplTest, PreviouslyDeniedPermissionNoActivation) { ...@@ -235,7 +233,8 @@ TEST_F(FontAccessManagerImplTest, PreviouslyDeniedPermissionNoActivation) {
} }
#endif #endif
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_MAC)
namespace { namespace {
void ValidateFontEnumerationBasic(FontEnumerationStatus status, void ValidateFontEnumerationBasic(FontEnumerationStatus status,
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_MAC)
#define PLATFORM_HAS_NATIVE_ENUMERATION_IMPL 1 #define PLATFORM_HAS_NATIVE_ENUMERATION_IMPL 1
#endif #endif
......
// Copyright 2020 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 CONTENT_BROWSER_FONT_ACCESS_FONT_ENUMERATION_CACHE_MAC_H_
#define CONTENT_BROWSER_FONT_ACCESS_FONT_ENUMERATION_CACHE_MAC_H_
#include "base/memory/scoped_refptr.h"
#include "base/task_runner.h"
#include "content/browser/font_access/font_enumeration_cache.h"
#include "content/common/content_export.h"
using blink::mojom::FontEnumerationStatus;
namespace base {
template <typename T>
class NoDestructor;
}
namespace content {
// Mac implementation of FontEnumerationCache.
class CONTENT_EXPORT FontEnumerationCacheMac : public FontEnumerationCache {
public:
FontEnumerationCacheMac();
~FontEnumerationCacheMac();
// Disallow Copy and Assign
FontEnumerationCacheMac(const FontEnumerationCacheMac&) = delete;
FontEnumerationCacheMac operator=(const FontEnumerationCacheMac&) = delete;
static FontEnumerationCacheMac* GetInstance();
// FontEnumerationCache methods.
void QueueShareMemoryRegionWhenReady(
scoped_refptr<base::TaskRunner> task_runner,
blink::mojom::FontAccessManager::EnumerateLocalFontsCallback callback)
override;
bool IsFontEnumerationCacheReady() override;
private:
friend class base::NoDestructor<FontEnumerationCacheMac>;
// This gives FontEnumerationCache::GetInstance access to the class
// constructor.
friend class FontEnumerationCache;
void SchedulePrepareFontEnumerationCache();
void PrepareFontEnumerationCache();
};
} // namespace content
#endif // CONTENT_BROWSER_FONT_ACCESS_FONT_ENUMERATION_CACHE_MAC_H_
// Copyright 2020 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 "content/browser/font_access/font_enumeration_cache_mac.h"
#import <AppKit/AppKit.h>
#import <CoreText/CoreText.h>
#include "base/feature_list.h"
#include "base/mac/foundation_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "third_party/blink/public/common/features.h"
namespace content {
namespace {
base::ScopedCFTypeRef<CFStringRef> GetLocalizedString(CTFontDescriptorRef fd,
CFStringRef attribute) {
return base::ScopedCFTypeRef<CFStringRef>(base::mac::CFCast<CFStringRef>(
CTFontDescriptorCopyLocalizedAttribute(fd, attribute, nullptr)));
}
base::ScopedCFTypeRef<CFStringRef> GetString(CTFontDescriptorRef fd,
CFStringRef attribute) {
return base::ScopedCFTypeRef<CFStringRef>(base::mac::CFCast<CFStringRef>(
CTFontDescriptorCopyAttribute(fd, attribute)));
}
} // namespace
FontEnumerationCacheMac::FontEnumerationCacheMac() = default;
FontEnumerationCacheMac::~FontEnumerationCacheMac() = default;
// static
FontEnumerationCache* FontEnumerationCache::GetInstance() {
static base::NoDestructor<FontEnumerationCacheMac> instance;
return instance.get();
}
void FontEnumerationCacheMac::QueueShareMemoryRegionWhenReady(
scoped_refptr<base::TaskRunner> task_runner,
blink::mojom::FontAccessManager::EnumerateLocalFontsCallback callback) {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
callbacks_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&FontEnumerationCacheMac::RunPendingCallback,
// Safe because this is an initialized singleton.
base::Unretained(this),
CallbackOnTaskRunner(std::move(task_runner), std::move(callback))));
if (!enumeration_cache_build_started_.IsSet()) {
enumeration_cache_build_started_.Set();
SchedulePrepareFontEnumerationCache();
}
}
bool FontEnumerationCacheMac::IsFontEnumerationCacheReady() {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
return enumeration_cache_built_.IsSet() && IsFontEnumerationCacheValid();
}
void FontEnumerationCacheMac::SchedulePrepareFontEnumerationCache() {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
scoped_refptr<base::SequencedTaskRunner> results_task_runner =
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT});
results_task_runner->PostTask(
FROM_HERE,
base::BindOnce(&FontEnumerationCacheMac::PrepareFontEnumerationCache,
// Safe because this is an initialized singleton.
base::Unretained(this)));
}
void FontEnumerationCacheMac::PrepareFontEnumerationCache() {
DCHECK(!enumeration_cache_built_.IsSet());
@autoreleasepool {
// Metrics.
const base::ElapsedTimer start_timer;
auto font_enumeration_table =
std::make_unique<blink::FontEnumerationTable>();
CFTypeRef values[1] = {kCFBooleanTrue};
base::ScopedCFTypeRef<CFDictionaryRef> options(CFDictionaryCreate(
kCFAllocatorDefault,
(const void**)kCTFontCollectionRemoveDuplicatesOption,
(const void**)&values,
/*numValues=*/1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
base::ScopedCFTypeRef<CTFontCollectionRef> collection(
CTFontCollectionCreateFromAvailableFonts(options));
base::ScopedCFTypeRef<CFArrayRef> font_descs(
CTFontCollectionCreateMatchingFontDescriptors(collection));
for (CFIndex i = 0; i < CFArrayGetCount(font_descs); ++i) {
CTFontDescriptorRef fd = base::mac::CFCast<CTFontDescriptorRef>(
CFArrayGetValueAtIndex(font_descs, i));
base::ScopedCFTypeRef<CFStringRef> cf_postscript_name =
GetString(fd, kCTFontNameAttribute);
base::ScopedCFTypeRef<CFStringRef> cf_full_name =
GetLocalizedString(fd, kCTFontDisplayNameAttribute);
base::ScopedCFTypeRef<CFStringRef> cf_family =
GetLocalizedString(fd, kCTFontFamilyNameAttribute);
blink::FontEnumerationTable_FontMetadata metadata;
metadata.set_postscript_name(
base::SysCFStringRefToUTF8(cf_postscript_name.get()).c_str());
metadata.set_full_name(
base::SysCFStringRefToUTF8(cf_full_name.get()).c_str());
metadata.set_family(base::SysCFStringRefToUTF8(cf_family.get()).c_str());
blink::FontEnumerationTable_FontMetadata* added_font_meta =
font_enumeration_table->add_fonts();
*added_font_meta = metadata;
}
enumeration_cache_memory_ = base::ReadOnlySharedMemoryRegion::Create(
font_enumeration_table->ByteSizeLong());
if (!IsFontEnumerationCacheValid() ||
!font_enumeration_table->SerializeToArray(
enumeration_cache_memory_.mapping.memory(),
enumeration_cache_memory_.mapping.size())) {
enumeration_cache_memory_ = base::MappedReadOnlyRegion();
}
enumeration_cache_built_.Set();
UMA_HISTOGRAM_MEDIUM_TIMES("Fonts.AccessAPI.EnumerationTime",
start_timer.Elapsed());
// Respond to pending and future requests.
StartCallbacksTaskQueue();
}
}
} // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment