blob: 8221e3699113726d6c3a8ea55496925de2246866 [file] [log] [blame]
// 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.h"
#include "base/feature_list.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/features.h"
namespace content {
FontEnumerationCache::FontEnumerationCache() {
InitializeCacheState();
}
FontEnumerationCache::~FontEnumerationCache() = default;
#if !defined(PLATFORM_HAS_LOCAL_FONT_ENUMERATION_IMPL)
// static
FontEnumerationCache* FontEnumerationCache::GetInstance() {
return nullptr;
}
#endif
void FontEnumerationCache::QueueShareMemoryRegionWhenReady(
scoped_refptr<base::TaskRunner> task_runner,
CacheTaskCallback callback) {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
callbacks_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&FontEnumerationCache::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 FontEnumerationCache::IsFontEnumerationCacheReady() {
DCHECK(base::FeatureList::IsEnabled(blink::features::kFontAccess));
return enumeration_cache_built_->IsSet() && IsFontEnumerationCacheValid();
}
void FontEnumerationCache::ResetStateForTesting() {
callbacks_task_runner_ =
base::MakeRefCounted<base::DeferredSequencedTaskRunner>();
InitializeCacheState();
}
base::ReadOnlySharedMemoryRegion FontEnumerationCache::DuplicateMemoryRegion() {
DCHECK(IsFontEnumerationCacheReady());
return enumeration_cache_memory_.region.Duplicate();
}
FontEnumerationCache::CallbackOnTaskRunner::CallbackOnTaskRunner(
scoped_refptr<base::TaskRunner> runner,
CacheTaskCallback callback)
: task_runner(std::move(runner)), callback(std::move(callback)) {}
FontEnumerationCache::CallbackOnTaskRunner::CallbackOnTaskRunner(
CallbackOnTaskRunner&& other) = default;
FontEnumerationCache::CallbackOnTaskRunner::~CallbackOnTaskRunner() = default;
void FontEnumerationCache::RunPendingCallback(
CallbackOnTaskRunner pending_callback) {
DCHECK(callbacks_task_runner_->RunsTasksInCurrentSequence());
pending_callback.task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(pending_callback.callback), status_,
DuplicateMemoryRegion()));
}
void FontEnumerationCache::StartCallbacksTaskQueue() {
callbacks_task_runner_->StartWithTaskRunner(
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::BEST_EFFORT}));
}
bool FontEnumerationCache::IsFontEnumerationCacheValid() const {
return enumeration_cache_memory_.IsValid() &&
enumeration_cache_memory_.mapping.size();
}
void FontEnumerationCache::BuildEnumerationCache(
std::unique_ptr<blink::FontEnumerationTable> table) {
DCHECK(!enumeration_cache_built_->IsSet());
// Postscript names, according to spec, are expected to be encoded in a subset
// of ASCII. See:
// https://docs.microsoft.com/en-us/typography/opentype/spec/name This is why
// a "simple" byte-wise comparison is used.
std::sort(table->mutable_fonts()->begin(), table->mutable_fonts()->end(),
[](const blink::FontEnumerationTable_FontMetadata& a,
const blink::FontEnumerationTable_FontMetadata& b) {
return a.postscript_name() < b.postscript_name();
});
enumeration_cache_memory_ =
base::ReadOnlySharedMemoryRegion::Create(table->ByteSizeLong());
if (!IsFontEnumerationCacheValid() ||
!table->SerializeToArray(enumeration_cache_memory_.mapping.memory(),
enumeration_cache_memory_.mapping.size())) {
enumeration_cache_memory_ = base::MappedReadOnlyRegion();
}
enumeration_cache_built_->Set();
}
void FontEnumerationCache::InitializeCacheState() {
enumeration_cache_memory_ = base::MappedReadOnlyRegion();
enumeration_cache_built_ = std::make_unique<base::AtomicFlag>();
enumeration_cache_build_started_ = std::make_unique<base::AtomicFlag>();
status_ = blink::mojom::FontEnumerationStatus::kOk;
}
} // namespace content