diff options
Diffstat (limited to 'chromium/content/child/dwrite_font_proxy')
3 files changed, 67 insertions, 33 deletions
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc index 7d717652d05..c06ca35000b 100644 --- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc +++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_impl_win.cc @@ -59,12 +59,8 @@ void InitializeDWriteFontProxy() { if (!g_font_collection) { mojo::PendingRemote<blink::mojom::DWriteFontProxy> dwrite_font_proxy; - if (g_connection_callback_override) { + if (g_connection_callback_override) dwrite_font_proxy = g_connection_callback_override->Run(); - } else if (auto* thread = ChildThread::Get()) { - thread->BindHostReceiver( - dwrite_font_proxy.InitWithNewPipeAndPassReceiver()); - } DWriteFontCollectionProxy::Create(&g_font_collection, factory.Get(), std::move(dwrite_font_proxy)); } diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc index 23330b6374b..b788c4ded4f 100644 --- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc +++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc @@ -17,7 +17,6 @@ #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" -#include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" #include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h" #include "content/public/child/child_thread.h" @@ -29,6 +28,33 @@ namespace content { namespace { +// Limits to 20 the number of family names that can be accessed by a renderer. +// This feature will be enabled for a subset of users to assess the impact on +// input delay. It will not ship as-is, because it breaks some pages. Local +// experiments show that accessing >20 fonts is typically done by fingerprinting +// scripts. +// TODO(https://crbug.com/1089390): Remove this feature when the experiment is +// complete. If the experiment shows a significant input delay improvement, +// replace with a more refined mitigation for pages that access many fonts. +const base::Feature kLimitFontFamilyNamesPerRenderer{ + "LimitFontFamilyNamesPerRenderer", base::FEATURE_DISABLED_BY_DEFAULT}; +constexpr size_t kFamilyNamesLimit = 20; + +// Family names that opted-out from the limit enforced by +// |kLimitFontFamilyNamesPerRenderer|. This is required because Blink uses these +// fonts as last resort and crashes if they can't be loaded. +const wchar_t* kLastResortFontNames[] = { + L"Sans", L"Arial", L"MS UI Gothic", L"Microsoft Sans Serif", + L"Segoe UI", L"Calibri", L"Times New Roman", L"Courier New"}; + +bool IsLastResortFontName(const base::string16& font_name) { + for (const wchar_t* last_resort_font_name : kLastResortFontNames) { + if (font_name == last_resort_font_name) + return true; + } + return false; +} + // This enum is used to define the buckets for an enumerated UMA histogram. // Hence, // (a) existing enumerated constants should never be deleted or reordered, and @@ -73,6 +99,13 @@ void LogFontProxyError(FontProxyError error) { FONT_PROXY_ERROR_MAX_VALUE); } +// Binds a DWriteFontProxy pending receiver. Must be invoked from the main +// thread. +void BindHostReceiverOnMainThread( + mojo::PendingReceiver<blink::mojom::DWriteFontProxy> pending_receiver) { + ChildThread::Get()->BindHostReceiver(std::move(pending_receiver)); +} + } // namespace HRESULT DWriteFontCollectionProxy::Create( @@ -95,7 +128,6 @@ HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* family_name, DCHECK(exists); TRACE_EVENT0("dwrite,fonts", "FontProxy::FindFamilyName"); - uint32_t family_index = 0; base::string16 name(family_name); auto iter = family_names_.find(name); @@ -105,6 +137,14 @@ HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* family_name, return S_OK; } + if (base::FeatureList::IsEnabled(kLimitFontFamilyNamesPerRenderer) && + family_names_.size() > kFamilyNamesLimit && !IsLastResortFontName(name)) { + *exists = FALSE; + *index = UINT32_MAX; + return S_OK; + } + + uint32_t family_index = 0; if (!GetFontProxy().FindFamily(name, &family_index)) { LogFontProxyError(FIND_FAMILY_SEND_FAILED); return E_FAIL; @@ -269,9 +309,8 @@ HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize( factory_ = factory; if (proxy) - SetProxy(std::move(proxy)); - else - main_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + font_proxy_.GetOrCreateValue().Bind(std::move(proxy)); + main_task_runner_ = base::ThreadTaskRunnerHandle::Get(); HRESULT hr = factory->RegisterFontCollectionLoader(this); DCHECK(SUCCEEDED(hr)); @@ -358,32 +397,19 @@ bool DWriteFontCollectionProxy::CreateFamily(UINT32 family_index) { return true; } -void DWriteFontCollectionProxy::SetProxy( - mojo::PendingRemote<blink::mojom::DWriteFontProxy> proxy) { - font_proxy_ = blink::mojom::ThreadSafeDWriteFontProxyPtr::Create( - std::move(proxy), base::ThreadPool::CreateSequencedTaskRunner( - {base::WithBaseSyncPrimitives()})); -} - blink::mojom::DWriteFontProxy& DWriteFontCollectionProxy::GetFontProxy() { - if (!font_proxy_) { - mojo::PendingRemote<blink::mojom::DWriteFontProxy> dwrite_font_proxy; + mojo::Remote<blink::mojom::DWriteFontProxy>& font_proxy = + font_proxy_.GetOrCreateValue(); + if (!font_proxy) { if (main_task_runner_->RunsTasksInCurrentSequence()) { - ChildThread::Get()->BindHostReceiver( - dwrite_font_proxy.InitWithNewPipeAndPassReceiver()); + BindHostReceiverOnMainThread(font_proxy.BindNewPipeAndPassReceiver()); } else { main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](mojo::PendingReceiver<blink::mojom::DWriteFontProxy> - receiver) { - ChildThread::Get()->BindHostReceiver(std::move(receiver)); - }, - dwrite_font_proxy.InitWithNewPipeAndPassReceiver())); + FROM_HERE, base::BindOnce(&BindHostReceiverOnMainThread, + font_proxy.BindNewPipeAndPassReceiver())); } - SetProxy(std::move(dwrite_font_proxy)); } - return **font_proxy_; + return *font_proxy; } DWriteFontFamilyProxy::DWriteFontFamilyProxy() = default; diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h index 576fa767650..0e14fa0c51b 100644 --- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h +++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h @@ -15,8 +15,10 @@ #include "base/files/memory_mapped_file.h" #include "base/macros.h" #include "base/strings/string16.h" +#include "base/threading/sequence_local_storage_slot.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom.h" namespace content { @@ -28,6 +30,8 @@ class DWriteFontFamilyProxy; // into a custom font collection. // This is needed because the sandbox interferes with DirectWrite's // communication with the system font service. +// This class can be accessed from any thread, but it is expected that a lock +// internal to DWrite prevents concurrent accesses. class DWriteFontCollectionProxy : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, @@ -36,6 +40,12 @@ class DWriteFontCollectionProxy IDWriteFontFileLoader> { public: // Factory method to avoid exporting the class and all it derives from. + // + // |proxy| is an optional DWriteFontProxy to use when the constructed + // DWriteFontCollectionProxy is used on the current sequence. DWriteFontProxy + // remotes will be bound via ChildThread when the constructed + // DWriteFontCollectionProxy is used from a sequence for which no + // DWriteFontProxy has been provided. static CONTENT_EXPORT HRESULT Create(DWriteFontCollectionProxy** proxy_out, IDWriteFactory* dwrite_factory, @@ -92,14 +102,16 @@ class DWriteFontCollectionProxy blink::mojom::DWriteFontProxy& GetFontProxy(); private: - void SetProxy(mojo::PendingRemote<blink::mojom::DWriteFontProxy> proxy); - Microsoft::WRL::ComPtr<IDWriteFactory> factory_; std::vector<Microsoft::WRL::ComPtr<DWriteFontFamilyProxy>> families_; std::map<base::string16, UINT32> family_names_; UINT32 family_count_ = UINT_MAX; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - scoped_refptr<blink::mojom::ThreadSafeDWriteFontProxyPtr> font_proxy_; + // Per-sequence mojo::Remote<DWriteFontProxy>. This is preferred to a + // mojo::SharedRemote, which would force a thread hop for each call that + // doesn't originate from the "bound" sequence. + base::SequenceLocalStorageSlot<mojo::Remote<blink::mojom::DWriteFontProxy>> + font_proxy_; DISALLOW_ASSIGN(DWriteFontCollectionProxy); }; |