blob: d5c361895bf51e3acde72ec80c73374ab4165501 [file] [log] [blame]
// Copyright 2015 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 "components/font_service/public/cpp/font_service_thread.h"
#include <utility>
#include "base/bind.h"
#include "base/files/file.h"
#include "base/synchronization/waitable_event.h"
#include "components/font_service/public/cpp/mapped_font_file.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/platform_handle/platform_handle_functions.h"
namespace font_service {
namespace internal {
namespace {
const char kFontThreadName[] = "Font_Proxy_Thread";
} // namespace
FontServiceThread::FontServiceThread(FontServicePtr font_service)
: base::Thread(kFontThreadName),
font_service_info_(font_service.PassInterface()) {
base::Thread::Options options;
options.message_pump_factory =
base::Bind(&mojo::common::MessagePumpMojo::Create);
StartWithOptions(options);
}
bool FontServiceThread::MatchFamilyName(
const char family_name[],
SkTypeface::Style requested_style,
SkFontConfigInterface::FontIdentity* out_font_identity,
SkString* out_family_name,
SkTypeface::Style* out_style) {
DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId());
bool out_valid = false;
// This proxies to the other thread, which proxies to mojo. Only on the reply
// from mojo do we return from this.
base::WaitableEvent done_event(false, false);
task_runner()->PostTask(
FROM_HERE,
base::Bind(&FontServiceThread::MatchFamilyNameImpl, this, &done_event,
family_name, requested_style, &out_valid, out_font_identity,
out_family_name, out_style));
done_event.Wait();
return out_valid;
}
scoped_refptr<MappedFontFile> FontServiceThread::OpenStream(
const SkFontConfigInterface::FontIdentity& identity) {
DCHECK_NE(GetThreadId(), base::PlatformThread::CurrentId());
base::File stream_file;
// This proxies to the other thread, which proxies to mojo. Only on the reply
// from mojo do we return from this.
base::WaitableEvent done_event(false, false);
task_runner()->PostTask(FROM_HERE,
base::Bind(&FontServiceThread::OpenStreamImpl, this,
&done_event, &stream_file, identity.fID));
done_event.Wait();
if (!stream_file.IsValid()) {
NOTREACHED();
return nullptr;
}
// Converts the file to out internal type.
scoped_refptr<MappedFontFile> mapped_font_file =
new MappedFontFile(identity.fID);
if (!mapped_font_file->Initialize(std::move(stream_file)))
return nullptr;
return mapped_font_file;
}
FontServiceThread::~FontServiceThread() {
Stop();
}
void FontServiceThread::MatchFamilyNameImpl(
base::WaitableEvent* done_event,
const char family_name[],
SkTypeface::Style requested_style,
bool* out_valid,
SkFontConfigInterface::FontIdentity* out_font_identity,
SkString* out_family_name,
SkTypeface::Style* out_style) {
DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId());
font_service_->MatchFamilyName(
mojo::String(family_name), static_cast<TypefaceStyle>(requested_style),
base::Bind(&FontServiceThread::OnMatchFamilyNameComplete, this,
done_event, out_valid, out_font_identity, out_family_name,
out_style));
}
void FontServiceThread::OnMatchFamilyNameComplete(
base::WaitableEvent* done_event,
bool* out_valid,
SkFontConfigInterface::FontIdentity* out_font_identity,
SkString* out_family_name,
SkTypeface::Style* out_style,
FontIdentityPtr font_identity,
mojo::String family_name,
TypefaceStyle style) {
DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId());
*out_valid = font_identity;
if (font_identity) {
out_font_identity->fID = font_identity->id;
out_font_identity->fTTCIndex = font_identity->ttc_index;
out_font_identity->fString = font_identity->str_representation.data();
// TODO(erg): fStyle isn't set. This is rather odd, however it matches the
// behaviour of the current Linux IPC version.
*out_family_name = family_name.data();
*out_style = static_cast<SkTypeface::Style>(style);
}
done_event->Signal();
}
void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event,
base::File* output_file,
const uint32_t id_number) {
DCHECK_EQ(GetThreadId(), base::PlatformThread::CurrentId());
font_service_->OpenStream(
id_number, base::Bind(&FontServiceThread::OnOpenStreamComplete, this,
done_event, output_file));
}
void FontServiceThread::OnOpenStreamComplete(base::WaitableEvent* done_event,
base::File* output_file,
mojo::ScopedHandle handle) {
if (handle.is_valid()) {
MojoPlatformHandle platform_handle;
CHECK(MojoExtractPlatformHandle(handle.release().value(),
&platform_handle) == MOJO_RESULT_OK);
*output_file = base::File(platform_handle);
}
done_event->Signal();
}
void FontServiceThread::Init() {
font_service_.Bind(std::move(font_service_info_));
}
void FontServiceThread::CleanUp() {
font_service_.reset();
}
} // namespace internal
} // namespace font_service