summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/font_service/BUILD.gn36
-rw-r--r--components/font_service/DEPS9
-rw-r--r--components/font_service/font_service_app.cc123
-rw-r--r--components/font_service/font_service_app.h53
-rw-r--r--components/font_service/main.cc12
-rw-r--r--components/font_service/public/cpp/BUILD.gn27
-rw-r--r--components/font_service/public/cpp/font_loader.cc63
-rw-r--r--components/font_service/public/cpp/font_loader.h67
-rw-r--r--components/font_service/public/cpp/font_service_thread.cc158
-rw-r--r--components/font_service/public/cpp/font_service_thread.h97
-rw-r--r--components/font_service/public/cpp/mapped_font_file.cc48
-rw-r--r--components/font_service/public/cpp/mapped_font_file.h54
-rw-r--r--components/font_service/public/interfaces/BUILD.gn11
-rw-r--r--components/font_service/public/interfaces/font_service.mojom38
-rw-r--r--components/html_viewer/BUILD.gn8
-rw-r--r--components/html_viewer/DEPS1
-rw-r--r--components/html_viewer/global_state.cc8
-rw-r--r--components/html_viewer/html_viewer_main.cc26
-rw-r--r--mandoline/app/core_services_initialization.cc4
-rw-r--r--mandoline/services/core_services/BUILD.gn4
-rw-r--r--mandoline/services/core_services/DEPS1
-rw-r--r--mandoline/services/core_services/core_services_application_delegate.cc8
-rw-r--r--mojo/runner/child_process.cc6
-rw-r--r--mojo/runner/linux_sandbox.cc4
-rw-r--r--mojo/shell/application_manager.cc2
25 files changed, 866 insertions, 2 deletions
diff --git a/components/font_service/BUILD.gn b/components/font_service/BUILD.gn
new file mode 100644
index 0000000..0e6f5d4
--- /dev/null
+++ b/components/font_service/BUILD.gn
@@ -0,0 +1,36 @@
+# 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.
+
+import("//mojo/public/mojo_application.gni")
+
+source_set("lib") {
+ sources = [
+ "font_service_app.cc",
+ "font_service_app.h",
+ ]
+
+ deps = [
+ "//components/font_service/public/interfaces",
+ "//mojo/application/public/cpp",
+ "//mojo/platform_handle",
+ "//third_party/mojo/src/mojo/public/cpp/bindings",
+ ]
+
+ public_deps = [
+ "//skia",
+ ]
+}
+
+mojo_native_application("font_service") {
+ sources = [
+ "main.cc",
+ ]
+
+ deps = [
+ ":lib",
+ "//base",
+ "//mojo/application/public/cpp",
+ "//third_party/mojo/src/mojo/public/cpp/bindings:callback",
+ ]
+}
diff --git a/components/font_service/DEPS b/components/font_service/DEPS
new file mode 100644
index 0000000..45a4dee
--- /dev/null
+++ b/components/font_service/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+ "+mojo/application",
+ "+mojo/common",
+ "+mojo/message_pump",
+ "+mojo/platform_handle",
+ "+skia",
+ "+third_party/mojo/src/mojo/public",
+ "+third_party/skia/include",
+]
diff --git a/components/font_service/font_service_app.cc b/components/font_service/font_service_app.cc
new file mode 100644
index 0000000..77f03a4
--- /dev/null
+++ b/components/font_service/font_service_app.cc
@@ -0,0 +1,123 @@
+// 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/font_service_app.h"
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/platform_handle/platform_handle_functions.h"
+
+COMPILE_ASSERT(static_cast<uint32>(SkTypeface::kNormal) ==
+ static_cast<uint32>(font_service::TYPEFACE_STYLE_NORMAL),
+ typeface_flags_should_match);
+COMPILE_ASSERT(static_cast<uint32>(SkTypeface::kBold) ==
+ static_cast<uint32>(font_service::TYPEFACE_STYLE_BOLD),
+ typeface_flags_should_match);
+COMPILE_ASSERT(static_cast<uint32>(SkTypeface::kItalic) ==
+ static_cast<uint32>(font_service::TYPEFACE_STYLE_ITALIC),
+ typeface_flags_should_match);
+COMPILE_ASSERT(
+ static_cast<uint32>(SkTypeface::kBoldItalic) ==
+ static_cast<uint32>(font_service::TYPEFACE_STYLE_BOLD_ITALIC),
+ typeface_flags_should_match);
+
+namespace {
+
+mojo::ScopedHandle GetHandleForPath(const base::FilePath& path) {
+ if (path.empty())
+ return mojo::ScopedHandle();
+
+ mojo::ScopedHandle to_pass;
+ base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!file.IsValid()) {
+ LOG(WARNING) << "file not valid, path=" << path.value();
+ return mojo::ScopedHandle();
+ }
+
+ MojoHandle mojo_handle;
+ MojoResult create_result =
+ MojoCreatePlatformHandleWrapper(file.TakePlatformFile(), &mojo_handle);
+ if (create_result != MOJO_RESULT_OK) {
+ LOG(WARNING) << "unable to create wrapper, path=" << path.value()
+ << "result=" << create_result;
+ return mojo::ScopedHandle();
+ }
+
+ return mojo::ScopedHandle(mojo::Handle(mojo_handle)).Pass();
+}
+
+} // namespace
+
+namespace font_service {
+
+FontServiceApp::FontServiceApp() {}
+
+FontServiceApp::~FontServiceApp() {}
+
+void FontServiceApp::Initialize(mojo::ApplicationImpl* app) {}
+
+bool FontServiceApp::ConfigureIncomingConnection(
+ mojo::ApplicationConnection* connection) {
+ connection->AddService(this);
+ return true;
+}
+
+void FontServiceApp::Create(mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<FontService> request) {
+ bindings_.AddBinding(this, request.Pass());
+}
+
+void FontServiceApp::MatchFamilyName(const mojo::String& family_name,
+ TypefaceStyle requested_style,
+ const MatchFamilyNameCallback& callback) {
+ SkFontConfigInterface::FontIdentity result_identity;
+ SkString result_family;
+ SkTypeface::Style result_style;
+ SkFontConfigInterface* fc =
+ SkFontConfigInterface::GetSingletonDirectInterface();
+ const bool r = fc->matchFamilyName(
+ family_name.data(), static_cast<SkTypeface::Style>(requested_style),
+ &result_identity, &result_family, &result_style);
+
+ if (!r) {
+ callback.Run(nullptr, "", TYPEFACE_STYLE_NORMAL);
+ return;
+ }
+
+ // Stash away the returned path, so we can give it an ID (index)
+ // which will later be given to us in a request to open the file.
+ int index = FindOrAddPath(result_identity.fString);
+
+ FontIdentityPtr identity(FontIdentity::New());
+ identity->id = static_cast<uint32_t>(index);
+ identity->ttc_index = result_identity.fTTCIndex;
+ identity->str_representation = result_identity.fString.c_str();
+
+ callback.Run(identity.Pass(), result_family.c_str(),
+ static_cast<TypefaceStyle>(result_style));
+}
+
+void FontServiceApp::OpenStream(uint32_t id_number,
+ const OpenStreamCallback& callback) {
+ mojo::ScopedHandle handle;
+ if (id_number < static_cast<uint32_t>(paths_.count())) {
+ handle =
+ GetHandleForPath(base::FilePath(paths_[id_number]->c_str())).Pass();
+ }
+
+ callback.Run(handle.Pass());
+}
+
+int FontServiceApp::FindOrAddPath(const SkString& path) {
+ int count = paths_.count();
+ for (int i = 0; i < count; ++i) {
+ if (path == *paths_[i])
+ return i;
+ }
+ *paths_.append() = new SkString(path);
+ return count;
+}
+
+} // namespace font_service
diff --git a/components/font_service/font_service_app.h b/components/font_service/font_service_app.h
new file mode 100644
index 0000000..9eda20a
--- /dev/null
+++ b/components/font_service/font_service_app.h
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
+#define COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
+
+#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/interface_factory.h"
+#include "mojo/common/weak_binding_set.h"
+#include "skia/ext/skia_utils_base.h"
+
+namespace font_service {
+
+class FontServiceApp : public mojo::ApplicationDelegate,
+ public mojo::InterfaceFactory<FontService>,
+ public FontService {
+ public:
+ FontServiceApp();
+ ~FontServiceApp() override;
+
+ private:
+ // ApplicationDelegate:
+ void Initialize(mojo::ApplicationImpl* app) override;
+ bool ConfigureIncomingConnection(
+ mojo::ApplicationConnection* connection) override;
+
+ // mojo::InterfaceFactory<FontService>:
+ void Create(mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<FontService> request) override;
+
+ // FontService:
+ void MatchFamilyName(const mojo::String& family_name,
+ TypefaceStyle requested_style,
+ const MatchFamilyNameCallback& callback) override;
+ void OpenStream(uint32_t id_number,
+ const OpenStreamCallback& callback) override;
+
+ int FindOrAddPath(const SkString& path);
+
+ mojo::WeakBindingSet<FontService> bindings_;
+
+ // We don't want to leak paths to our callers; we thus enumerate the paths of
+ // fonts.
+ SkTDArray<SkString*> paths_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontServiceApp);
+};
+
+} // namespace font_service
+
+#endif // COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
diff --git a/components/font_service/main.cc b/components/font_service/main.cc
new file mode 100644
index 0000000..9b234e6
--- /dev/null
+++ b/components/font_service/main.cc
@@ -0,0 +1,12 @@
+// 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/font_service_app.h"
+#include "mojo/application/public/cpp/application_runner.h"
+#include "third_party/mojo/src/mojo/public/c/system/main.h"
+
+MojoResult MojoMain(MojoHandle shell_handle) {
+ mojo::ApplicationRunner runner(new font_service::FontServiceApp);
+ return runner.Run(shell_handle);
+}
diff --git a/components/font_service/public/cpp/BUILD.gn b/components/font_service/public/cpp/BUILD.gn
new file mode 100644
index 0000000..52359b7
--- /dev/null
+++ b/components/font_service/public/cpp/BUILD.gn
@@ -0,0 +1,27 @@
+# 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.
+
+source_set("cpp") {
+ sources = [
+ "font_loader.cc",
+ "font_loader.h",
+ "font_service_thread.cc",
+ "font_service_thread.h",
+ "mapped_font_file.cc",
+ "mapped_font_file.h",
+ ]
+
+ deps = [
+ "../interfaces",
+ "//base",
+ "//mojo/application/public/cpp",
+ "//mojo/application/public/interfaces",
+ "//mojo/common",
+ "//mojo/message_pump",
+ "//mojo/platform_handle",
+ "//skia",
+ "//third_party/mojo/src/mojo/public/cpp/bindings",
+ "//third_party/mojo/src/mojo/public/cpp/system",
+ ]
+}
diff --git a/components/font_service/public/cpp/font_loader.cc b/components/font_service/public/cpp/font_loader.cc
new file mode 100644
index 0000000..8b63384
--- /dev/null
+++ b/components/font_service/public/cpp/font_loader.cc
@@ -0,0 +1,63 @@
+// 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_loader.h"
+
+#include "components/font_service/public/cpp/font_service_thread.h"
+#include "mojo/application/public/cpp/application_impl.h"
+
+namespace font_service {
+
+FontLoader::FontLoader(mojo::ApplicationImpl* application_impl) {
+ mojo::URLRequestPtr request(mojo::URLRequest::New());
+ request->url = mojo::String::From("mojo:font_service");
+ FontServicePtr font_service;
+ application_impl->ConnectToService(request.Pass(), &font_service);
+
+ thread_ = new internal::FontServiceThread(font_service.Pass());
+}
+
+FontLoader::~FontLoader() {}
+
+bool FontLoader::matchFamilyName(const char family_name[],
+ SkTypeface::Style requested,
+ FontIdentity* out_font_identifier,
+ SkString* out_family_name,
+ SkTypeface::Style* out_style) {
+ return thread_->MatchFamilyName(family_name, requested, out_font_identifier,
+ out_family_name, out_style);
+}
+
+SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) {
+ {
+ base::AutoLock lock(lock_);
+ auto mapped_font_files_it = mapped_font_files_.find(identity.fID);
+ if (mapped_font_files_it != mapped_font_files_.end())
+ return mapped_font_files_it->second->CreateMemoryStream();
+ }
+
+ scoped_refptr<internal::MappedFontFile> mapped_font_file =
+ thread_->OpenStream(identity);
+ if (!mapped_font_file)
+ return nullptr;
+
+ // Get notified with |mapped_font_file| is destroyed.
+ mapped_font_file->set_observer(this);
+
+ {
+ base::AutoLock lock(lock_);
+ auto mapped_font_files_it =
+ mapped_font_files_.insert(std::make_pair(mapped_font_file->font_id(),
+ mapped_font_file.get()))
+ .first;
+ return mapped_font_files_it->second->CreateMemoryStream();
+ }
+}
+
+void FontLoader::OnMappedFontFileDestroyed(internal::MappedFontFile* f) {
+ base::AutoLock lock(lock_);
+ mapped_font_files_.erase(f->font_id());
+}
+
+} // namespace font_service
diff --git a/components/font_service/public/cpp/font_loader.h b/components/font_service/public/cpp/font_loader.h
new file mode 100644
index 0000000..38e82e1
--- /dev/null
+++ b/components/font_service/public/cpp/font_loader.h
@@ -0,0 +1,67 @@
+// 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.
+
+#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
+#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "components/font_service/public/cpp/mapped_font_file.h"
+#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkFontConfigInterface.h"
+
+namespace mojo {
+class ApplicationImpl;
+}
+
+namespace font_service {
+namespace internal {
+class FontServiceThread;
+}
+
+// FontConfig implementation for Skia which proxies to the font service to get
+// out of the sandbox. This methods of this class (as imposed by blink
+// requirements) may be called on any thread. (Because of this restriction,
+// also see the FontServiceThread class.)
+//
+// This is the mojo equivalent to content/common/font_config_ipc_linux.h
+class FontLoader : public SkFontConfigInterface,
+ public internal::MappedFontFile::Observer {
+ public:
+ explicit FontLoader(mojo::ApplicationImpl* application_impl);
+ ~FontLoader() override;
+
+ // SkFontConfigInterface:
+ bool matchFamilyName(const char family_name[],
+ SkTypeface::Style requested,
+ FontIdentity* out_font_identifier,
+ SkString* out_family_name,
+ SkTypeface::Style* out_style) override;
+ SkStreamAsset* openStream(const FontIdentity& identity) override;
+
+ private:
+ // internal::MappedFontFile::Observer:
+ void OnMappedFontFileDestroyed(internal::MappedFontFile* f) override;
+
+ // Thread to own the mojo message pipe. Because FontLoader can be called on
+ // multiple threads, we create a dedicated thread to send and receive mojo
+ // message calls.
+ scoped_refptr<internal::FontServiceThread> thread_;
+
+ // Lock preventing multiple threads from opening font file and accessing
+ // |mapped_font_files_| map at the same time.
+ base::Lock lock_;
+
+ // Maps font identity ID to the memory-mapped file with font data.
+ base::hash_map<uint32_t, internal::MappedFontFile*> mapped_font_files_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontLoader);
+};
+
+} // namespace font_service
+
+#endif // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
diff --git a/components/font_service/public/cpp/font_service_thread.cc b/components/font_service/public/cpp/font_service_thread.cc
new file mode 100644
index 0000000..ca2ab05
--- /dev/null
+++ b/components/font_service/public/cpp/font_service_thread.cc
@@ -0,0 +1,158 @@
+// 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 "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().Pass()) {
+ 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(stream_file.Pass()))
+ 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).Pass();
+ }
+
+ done_event->Signal();
+}
+
+void FontServiceThread::Init() {
+ font_service_.Bind(font_service_info_.Pass());
+}
+
+void FontServiceThread::CleanUp() {
+ font_service_.reset();
+}
+
+} // namespace internal
+} // namespace font_service
diff --git a/components/font_service/public/cpp/font_service_thread.h b/components/font_service/public/cpp/font_service_thread.h
new file mode 100644
index 0000000..6a47540
--- /dev/null
+++ b/components/font_service/public/cpp/font_service_thread.h
@@ -0,0 +1,97 @@
+// 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.
+
+#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
+#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
+
+#include "base/files/file.h"
+#include "base/threading/thread.h"
+#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkFontConfigInterface.h"
+
+namespace font_service {
+namespace internal {
+
+class MappedFontFile;
+
+// The thread which services font requests.
+//
+// The SkFontConfigInterface is a global singleton which can be accessed from
+// multiple threads. However, mojo pipes are bound to a single thread. Because
+// of this mismatch, we create a thread which owns the mojo pipe, sends and
+// receives messages. The multiple threads which call through FontLoader class
+// do blocking message calls to this thread.
+class FontServiceThread : public base::Thread,
+ public base::RefCountedThreadSafe<FontServiceThread> {
+ public:
+ explicit FontServiceThread(FontServicePtr font_service);
+
+ // These methods are proxies which run on your thread, post a blocking task
+ // to the FontServiceThread, and wait on an event signaled from the callback.
+ bool MatchFamilyName(const char family_name[],
+ SkTypeface::Style requested_style,
+ SkFontConfigInterface::FontIdentity* out_font_identity,
+ SkString* out_family_name,
+ SkTypeface::Style* out_style);
+ scoped_refptr<MappedFontFile> OpenStream(
+ const SkFontConfigInterface::FontIdentity& identity);
+
+ private:
+ friend class base::RefCountedThreadSafe<FontServiceThread>;
+ ~FontServiceThread() override;
+
+ // Methods which run on the FontServiceThread. The public MatchFamilyName
+ // calls this method, this method calls the mojo interface, and sets up the
+ // callback to OnMatchFamilyNameComplete.
+ void 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);
+
+ // Called on the FontServiceThread in response to receiving a message from
+ // our MatchFamily mojo IPC. This writes the data returned by mojo, and then
+ // signals |done_event| to wake up the other thread.
+ void 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);
+
+ // Implementation of OpenStream; same threading restrictions as MatchFamily.
+ void OpenStreamImpl(base::WaitableEvent* done_event,
+ base::File* output_file,
+ const uint32_t id_number);
+ void OnOpenStreamComplete(base::WaitableEvent* done_event,
+ base::File* output_file,
+ mojo::ScopedHandle handle);
+
+ // base::Thread
+ void Init() override;
+ void CleanUp() override;
+
+ // This member is used to safely pass data from one thread to another. It is
+ // set in the constructor and is consumed in Init().
+ mojo::InterfacePtrInfo<FontService> font_service_info_;
+
+ // This member is set in Init(). It takes |font_service_info_|, which is
+ // non-thread bound, and binds it to the newly created thread.
+ mojo::InterfacePtr<FontService> font_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(FontServiceThread);
+};
+
+} // namespace internal
+} // namespace font_service
+
+#endif // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
diff --git a/components/font_service/public/cpp/mapped_font_file.cc b/components/font_service/public/cpp/mapped_font_file.cc
new file mode 100644
index 0000000..98deaaf
--- /dev/null
+++ b/components/font_service/public/cpp/mapped_font_file.cc
@@ -0,0 +1,48 @@
+// 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/mapped_font_file.h"
+
+#include "base/files/file_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "skia/ext/refptr.h"
+#include "skia/ext/skia_utils_base.h"
+#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkStream.h"
+
+namespace font_service {
+namespace internal {
+
+MappedFontFile::MappedFontFile(uint32_t font_id)
+ : font_id_(font_id), observer_(nullptr) {}
+
+bool MappedFontFile::Initialize(base::File file) {
+ base::ThreadRestrictions::ScopedAllowIO allow_mmap;
+ return mapped_font_file_.Initialize(file.Pass());
+}
+
+SkMemoryStream* MappedFontFile::CreateMemoryStream() {
+ DCHECK(mapped_font_file_.IsValid());
+ auto data = skia::AdoptRef(
+ SkData::NewWithProc(mapped_font_file_.data(), mapped_font_file_.length(),
+ &MappedFontFile::ReleaseProc, this));
+ if (!data)
+ return nullptr;
+ AddRef();
+ return new SkMemoryStream(data.get());
+}
+
+MappedFontFile::~MappedFontFile() {
+ if (observer_)
+ observer_->OnMappedFontFileDestroyed(this);
+}
+
+// static
+void MappedFontFile::ReleaseProc(const void* ptr, void* context) {
+ base::ThreadRestrictions::ScopedAllowIO allow_munmap;
+ static_cast<MappedFontFile*>(context)->Release();
+}
+
+} // namespace internal
+} // namespace font_service
diff --git a/components/font_service/public/cpp/mapped_font_file.h b/components/font_service/public/cpp/mapped_font_file.h
new file mode 100644
index 0000000..c860fed
--- /dev/null
+++ b/components/font_service/public/cpp/mapped_font_file.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
+#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
+
+#include "base/files/file.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/skia/include/core/SkStream.h"
+
+namespace font_service {
+namespace internal {
+
+// Owns the memory of the mmaped file that we get back from the font_service.
+//
+// This class is an implementation detail and shouldn't be used by consumers.
+class MappedFontFile : public base::RefCountedThreadSafe<MappedFontFile> {
+ public:
+ class Observer {
+ public:
+ ~Observer() {}
+
+ // Called when a MappedFontFile is destroyed.
+ virtual void OnMappedFontFileDestroyed(MappedFontFile* f) = 0;
+ };
+
+ explicit MappedFontFile(uint32_t font_id);
+
+ uint32_t font_id() const { return font_id_; }
+
+ void set_observer(Observer* observer) { observer_ = observer; }
+
+ bool Initialize(base::File file);
+
+ SkMemoryStream* CreateMemoryStream();
+
+ private:
+ friend class base::RefCountedThreadSafe<MappedFontFile>;
+
+ ~MappedFontFile();
+
+ static void ReleaseProc(const void* ptr, void* context);
+
+ uint32_t font_id_;
+ base::MemoryMappedFile mapped_font_file_;
+ Observer* observer_;
+};
+
+} // namespace internal
+} // namespace font_service
+
+#endif // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
diff --git a/components/font_service/public/interfaces/BUILD.gn b/components/font_service/public/interfaces/BUILD.gn
new file mode 100644
index 0000000..db1a2dd
--- /dev/null
+++ b/components/font_service/public/interfaces/BUILD.gn
@@ -0,0 +1,11 @@
+# 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.
+
+import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
+
+mojom("interfaces") {
+ sources = [
+ "font_service.mojom",
+ ]
+}
diff --git a/components/font_service/public/interfaces/font_service.mojom b/components/font_service/public/interfaces/font_service.mojom
new file mode 100644
index 0000000..3d53b00
--- /dev/null
+++ b/components/font_service/public/interfaces/font_service.mojom
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+module font_service;
+
+enum TypefaceStyle {
+ NORMAL = 0,
+ BOLD = 0x01,
+ ITALIC = 0x02,
+ BOLD_ITALIC = 0x03
+};
+
+// A reference to specific font on the font service.
+struct FontIdentity {
+ uint32 id;
+ int32 ttc_index;
+ // TODO(erg): So the string is supposed to be a path. However, the current
+ // chrome code goes out of its way to send this to the renderer process, and
+ // it is passed to blink, even though the openStream() IPC in chrome uses the
+ // id number instead. Do more investigation about what we need to do to plug
+ // this system path leak.
+ string str_representation;
+};
+
+// Loads and resolves fonts.
+//
+// We still need to load fonts from within a sandboxed process. We set
+// up a service to match fonts and load them,
+interface FontService {
+ // Returns the best match for |family_name| and |style|. On error, returns a
+ // null |identity|.
+ MatchFamilyName(string family_name, TypefaceStyle style) =>
+ (FontIdentity? identity, string family_name, TypefaceStyle style);
+
+ // Returns a handle to the raw font specified by |id_number|.
+ OpenStream(uint32 id_number) => (handle font_handle);
+};
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn
index dcbdaf2..ab49118 100644
--- a/components/html_viewer/BUILD.gn
+++ b/components/html_viewer/BUILD.gn
@@ -185,6 +185,10 @@ source_set("lib") {
sources += [ "html_viewer_version.rc" ]
}
+ if (is_linux && !is_android) {
+ deps += [ "//components/font_service/public/cpp" ]
+ }
+
data_deps = [
"//components/clipboard",
"//components/view_manager",
@@ -316,4 +320,8 @@ mojo_native_application("apptests") {
":html_viewer",
"//components/view_manager",
]
+
+ if (is_linux && !is_android) {
+ data_deps += [ "//components/font_service" ]
+ }
}
diff --git a/components/html_viewer/DEPS b/components/html_viewer/DEPS
index 8355e5b..4f2c54e 100644
--- a/components/html_viewer/DEPS
+++ b/components/html_viewer/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+cc",
"+components/clipboard",
"+components/devtools_service/public",
+ "+components/font_service/public",
"+components/gpu",
"+components/message_port",
"+components/mime_util",
diff --git a/components/html_viewer/global_state.cc b/components/html_viewer/global_state.cc
index ec0f570..870c4e7 100644
--- a/components/html_viewer/global_state.cc
+++ b/components/html_viewer/global_state.cc
@@ -22,6 +22,10 @@
#include "ui/mojo/init/ui_init.h"
#include "v8/include/v8.h"
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+#include "components/font_service/public/cpp/font_loader.h"
+#endif
+
namespace html_viewer {
namespace {
@@ -93,6 +97,10 @@ void GlobalState::InitIfNecessary(const gfx::Size& screen_size_in_pixels,
return;
}
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+ SkFontConfigInterface::SetGlobal(new font_service::FontLoader(app_));
+#endif
+
ui_init_.reset(
new ui::mojo::UIInit(screen_size_in_pixels, device_pixel_ratio));
base::DiscardableMemoryAllocator::SetInstance(&discardable_memory_allocator_);
diff --git a/components/html_viewer/html_viewer_main.cc b/components/html_viewer/html_viewer_main.cc
index 9afd58d..79349639 100644
--- a/components/html_viewer/html_viewer_main.cc
+++ b/components/html_viewer/html_viewer_main.cc
@@ -6,6 +6,32 @@
#include "mojo/application/public/cpp/application_runner.h"
#include "third_party/mojo/src/mojo/public/c/system/main.h"
+// TODO(erg): Much of this will be the same between mojo applications. Maybe we
+// could centralize this code?
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+#include "base/rand_util.h"
+#include "base/sys_info.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+
+// TODO(erg): Much of this was coppied from zygote_main_linux.cc
+extern "C" {
+void __attribute__((visibility("default"))) MojoSandboxWarm() {
+ base::RandUint64();
+ base::SysInfo::AmountOfPhysicalMemory();
+ base::SysInfo::MaxSharedMemorySize();
+ base::SysInfo::NumberOfProcessors();
+
+ // ICU DateFormat class (used in base/time_format.cc) needs to get the
+ // Olson timezone ID by accessing the zoneinfo files on disk. After
+ // TimeZone::createDefault is called once here, the timezone ID is
+ // cached and there's no more need to access the file system.
+ scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+
+ // TODO(erg): Perform OpenSSL warmup; it wants access to /dev/urandom.
+}
+}
+#endif // defined(OS_LINUX) && !defined(OS_ANDROID)
+
MojoResult MojoMain(MojoHandle shell_handle) {
mojo::ApplicationRunner runner(new html_viewer::HTMLViewer);
return runner.Run(shell_handle);
diff --git a/mandoline/app/core_services_initialization.cc b/mandoline/app/core_services_initialization.cc
index 304fe1e..7f1dd12 100644
--- a/mandoline/app/core_services_initialization.cc
+++ b/mandoline/app/core_services_initialization.cc
@@ -16,6 +16,10 @@ void InitCoreServicesForContext(mojo::runner::Context* context) {
GURL("mojo:clipboard"), GURL("mojo:core_services"), "Sandboxed Core");
manager->RegisterApplicationPackageAlias(GURL("mojo:filesystem"),
GURL("mojo:core_services"), "Files");
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+ manager->RegisterApplicationPackageAlias(GURL("mojo:font_service"),
+ GURL("mojo:core_services"), "Files");
+#endif
#if !defined(OS_ANDROID)
// On Android, these are Java apps which are loaded in the shell process.
manager->RegisterApplicationPackageAlias(GURL("mojo:view_manager"),
diff --git a/mandoline/services/core_services/BUILD.gn b/mandoline/services/core_services/BUILD.gn
index 2a34b61..cf640e6 100644
--- a/mandoline/services/core_services/BUILD.gn
+++ b/mandoline/services/core_services/BUILD.gn
@@ -60,6 +60,10 @@ source_set("sources") {
]
}
+ if (is_linux && !is_android) {
+ deps += [ "//components/font_service:lib" ]
+ }
+
if (use_aura) {
deps += [
"//components/view_manager/public/cpp",
diff --git a/mandoline/services/core_services/DEPS b/mandoline/services/core_services/DEPS
index 90dcddc..ca0908aa 100644
--- a/mandoline/services/core_services/DEPS
+++ b/mandoline/services/core_services/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+components/clipboard",
"+components/filesystem",
+ "+components/font_service",
"+components/resource_provider",
"+components/view_manager",
"+mojo/application",
diff --git a/mandoline/services/core_services/core_services_application_delegate.cc b/mandoline/services/core_services/core_services_application_delegate.cc
index 7805164..d3ef946 100644
--- a/mandoline/services/core_services/core_services_application_delegate.cc
+++ b/mandoline/services/core_services/core_services_application_delegate.cc
@@ -28,6 +28,10 @@
#include "mojo/services/network/network_service_delegate.h"
#endif
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+#include "components/font_service/font_service_app.h"
+#endif
+
namespace core_services {
// A helper class for hosting a mojo::ApplicationImpl on its own thread.
@@ -130,6 +134,10 @@ void CoreServicesApplicationDelegate::StartApplication(
delegate.reset(new clipboard::ClipboardApplicationDelegate);
} else if (url == "mojo://filesystem/") {
delegate.reset(new filesystem::FileSystemApp);
+#if defined(OS_LINUX) && !defined(OS_ANDROID)
+ } else if (url == "mojo://font_service/") {
+ delegate.reset(new font_service::FontServiceApp);
+#endif
} else if (url == "mojo://surfaces_service/") {
delegate.reset(new surfaces::SurfacesServiceApplication);
} else if (url == "mojo://tracing/") {
diff --git a/mojo/runner/child_process.cc b/mojo/runner/child_process.cc
index eda7829..85ce4b3 100644
--- a/mojo/runner/child_process.cc
+++ b/mojo/runner/child_process.cc
@@ -310,7 +310,13 @@ int ChildProcessMain() {
if (sandbox_warm)
sandbox_warm();
+ // TODO(erg,jln): Allowing access to all of /dev/shm/ makes it easy to
+ // spy on other shared memory using processes. This is a temporary hack
+ // so that we have some sandbox until we have proper shared memory
+ // support integrated into mojo.
std::vector<BrokerFilePermission> permissions;
+ permissions.push_back(
+ BrokerFilePermission::ReadWriteCreateUnlinkRecursive("/dev/shm/"));
sandbox.reset(new mandoline::LinuxSandbox(permissions));
sandbox->Warmup();
sandbox->EngageNamespaceSandbox();
diff --git a/mojo/runner/linux_sandbox.cc b/mojo/runner/linux_sandbox.cc
index 06165b2..fb6af97 100644
--- a/mojo/runner/linux_sandbox.cc
+++ b/mojo/runner/linux_sandbox.cc
@@ -92,8 +92,8 @@ class SandboxPolicy : public sandbox::bpf_dsl::Policy {
LinuxSandbox::LinuxSandbox(const std::vector<BrokerFilePermission>& permissions)
: broker_(new sandbox::syscall_broker::BrokerProcess(EPERM, permissions)) {
- broker_->Init(
- base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities));
+ CHECK(broker_->Init(
+ base::Bind<bool (*)()>(&sandbox::Credentials::DropAllCapabilities)));
policy_.reset(new SandboxPolicy(broker_.get()));
}
diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc
index 17de9de..bbe68cf3 100644
--- a/mojo/shell/application_manager.cc
+++ b/mojo/shell/application_manager.cc
@@ -383,6 +383,8 @@ void ApplicationManager::HandleFetchCallback(
bool start_sandboxed = false;
if (app_url == GURL("mojo://core_services/") && qualifier == "Sandboxed Core")
start_sandboxed = true;
+ else if (app_url == GURL("mojo://html_viewer/"))
+ start_sandboxed = true;
fetcher->AsPath(blocking_pool_,
base::Bind(&ApplicationManager::RunNativeApplication,