1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_FontFaceSetImpl_h
8 #define mozilla_dom_FontFaceSetImpl_h
10 #include "mozilla/dom/FontFace.h"
11 #include "mozilla/dom/FontFaceSetBinding.h"
12 #include "mozilla/DOMEventTargetHelper.h"
13 #include "mozilla/FontPropertyTypes.h"
14 #include "mozilla/RecursiveMutex.h"
15 #include "gfxUserFontSet.h"
16 #include "nsICSSLoaderObserver.h"
17 #include "nsIDOMEventListener.h"
21 struct gfxFontFaceSrc
;
22 class gfxFontSrcPrincipal
;
23 class gfxUserFontEntry
;
24 class nsFontFaceLoader
;
27 class nsPIDOMWindowInner
;
30 struct StyleLockedFontFaceRule
;
31 class PostTraversalTask
;
37 } // namespace mozilla
39 namespace mozilla::dom
{
41 class FontFaceSetImpl
: public nsISupports
, public gfxUserFontSet
{
42 NS_DECL_THREADSAFE_ISUPPORTS
47 already_AddRefed
<gfxFontSrcPrincipal
> GetStandardFontLoadPrincipal()
50 void RecordFontLoadDone(uint32_t aFontSize
, TimeStamp aDoneTime
) override
;
52 bool BypassCache() final
{ return mBypassCache
; }
54 void ForgetLocalFaces() final
;
57 virtual nsresult
CreateChannelForSyncLoadFontData(
58 nsIChannel
** aOutChannel
, gfxUserFontEntry
* aFontToLoad
,
59 const gfxFontFaceSrc
* aFontFaceSrc
) = 0;
63 bool GetPrivateBrowsing() override
{ return mPrivateBrowsing
; }
64 nsresult
SyncLoadFontData(gfxUserFontEntry
* aFontToLoad
,
65 const gfxFontFaceSrc
* aFontFaceSrc
,
67 uint32_t& aBufferLength
) override
;
68 nsresult
LogMessage(gfxUserFontEntry
* aUserFontEntry
, uint32_t aSrcIndex
,
70 uint32_t aFlags
= nsIScriptError::errorFlag
,
71 nsresult aStatus
= NS_OK
) override
;
72 void DoRebuildUserFontSet() override
;
73 already_AddRefed
<gfxUserFontEntry
> CreateUserFontEntry(
74 nsTArray
<gfxFontFaceSrc
>&& aFontFaceSrcList
,
75 gfxUserFontAttributes
&& aAttr
) override
;
77 already_AddRefed
<gfxUserFontFamily
> GetFamily(
78 const nsACString
& aFamilyName
) final
;
80 explicit FontFaceSetImpl(FontFaceSet
* aOwner
);
82 void DestroyLoaders();
85 virtual void Destroy();
86 virtual bool IsOnOwningThread() = 0;
88 virtual void AssertIsOnOwningThread() = 0;
90 void AssertIsOnOwningThread() {}
92 virtual void DispatchToOwningThread(const char* aName
,
93 std::function
<void()>&& aFunc
) = 0;
95 // Called by nsFontFaceLoader when the loader has completed normally.
96 // It's removed from the mLoaders set.
97 virtual void RemoveLoader(nsFontFaceLoader
* aLoader
);
99 virtual bool UpdateRules(const nsTArray
<nsFontFaceRuleContainer
>& aRules
) {
100 MOZ_ASSERT_UNREACHABLE("Not implemented!");
104 // search for @font-face rule that matches a platform font entry
105 virtual StyleLockedFontFaceRule
* FindRuleForEntry(gfxFontEntry
* aFontEntry
) {
106 MOZ_ASSERT_UNREACHABLE("Not implemented!");
111 * Finds an existing entry in the user font cache or creates a new user
112 * font entry for the given FontFace object.
114 static already_AddRefed
<gfxUserFontEntry
>
115 FindOrCreateUserFontEntryFromFontFace(FontFaceImpl
* aFontFace
,
116 gfxUserFontAttributes
&& aAttr
,
120 * Notification method called by a FontFace to indicate that its loading
121 * status has changed.
123 virtual void OnFontFaceStatusChanged(FontFaceImpl
* aFontFace
);
126 * Notification method called by the nsPresContext to indicate that the
127 * refresh driver ticked and flushed style and layout.
130 virtual void DidRefresh() { MOZ_ASSERT_UNREACHABLE("Not implemented!"); }
132 virtual void FlushUserFontSet() = 0;
134 static nsPresContext
* GetPresContextFor(gfxUserFontSet
* aUserFontSet
) {
135 const auto* set
= static_cast<FontFaceSetImpl
*>(aUserFontSet
);
136 return set
? set
->GetPresContext() : nullptr;
139 virtual void RefreshStandardFontLoadPrincipal();
141 virtual dom::Document
* GetDocument() const { return nullptr; }
143 virtual already_AddRefed
<URLExtraData
> GetURLExtraData() = 0;
145 // -- Web IDL --------------------------------------------------------------
147 virtual void EnsureReady() {}
148 dom::FontFaceSetLoadStatus
Status();
150 virtual bool Add(FontFaceImpl
* aFontFace
, ErrorResult
& aRv
);
151 virtual void Clear();
152 virtual bool Delete(FontFaceImpl
* aFontFace
);
154 // For ServoStyleSet to know ahead of time whether a font is loadable.
155 virtual void CacheFontLoadability() {
156 MOZ_ASSERT_UNREACHABLE("Not implemented!");
159 virtual void MarkUserFontSetDirty() {}
162 * Checks to see whether it is time to resolve mReady and dispatch any
163 * "loadingdone" and "loadingerror" events.
165 virtual void CheckLoadingFinished();
167 virtual void FindMatchingFontFaces(const nsACString
& aFont
,
168 const nsAString
& aText
,
169 nsTArray
<FontFace
*>& aFontFaces
,
172 virtual void DispatchCheckLoadingFinishedAfterDelay();
175 ~FontFaceSetImpl() override
;
177 virtual uint64_t GetInnerWindowID() = 0;
180 * Returns whether the given FontFace is currently "in" the FontFaceSet.
182 bool HasAvailableFontFace(FontFaceImpl
* aFontFace
);
185 * Returns whether there might be any pending font loads, which should cause
186 * the mReady Promise not to be resolved yet.
188 virtual bool MightHavePendingFontLoads();
191 * Checks to see whether it is time to replace mReady and dispatch a
194 void CheckLoadingStarted();
197 * Callback for invoking CheckLoadingFinished after going through the
198 * event loop. See OnFontFaceStatusChanged.
200 void CheckLoadingFinishedAfterDelay();
202 void OnLoadingStarted();
203 void OnLoadingFinished();
205 // Note: if you add new cycle collected objects to FontFaceRecord,
206 // make sure to update FontFaceSet's cycle collection macros
208 struct FontFaceRecord
{
209 RefPtr
<FontFaceImpl
> mFontFace
;
210 Maybe
<StyleOrigin
> mOrigin
; // only relevant for mRuleFaces entries
213 // search for @font-face rule that matches a userfont font entry
214 virtual StyleLockedFontFaceRule
* FindRuleForUserFontEntry(
215 gfxUserFontEntry
* aUserFontEntry
) {
219 virtual void FindMatchingFontFaces(
220 const nsTHashSet
<FontFace
*>& aMatchingFaces
,
221 nsTArray
<FontFace
*>& aFontFaces
);
223 class UpdateUserFontEntryRunnable
;
224 void UpdateUserFontEntry(gfxUserFontEntry
* aEntry
,
225 gfxUserFontAttributes
&& aAttr
);
227 nsresult
CheckFontLoad(const gfxFontFaceSrc
* aFontFaceSrc
,
228 gfxFontSrcPrincipal
** aPrincipal
, bool* aBypassCache
);
230 void InsertNonRuleFontFace(FontFaceImpl
* aFontFace
);
233 * Returns whether we have any loading FontFace objects in the FontFaceSet.
235 bool HasLoadingFontFaces();
237 // Whether mReady is pending, or would be when created.
238 bool ReadyPromiseIsPending() const;
240 // Helper function for HasLoadingFontFaces.
241 virtual void UpdateHasLoadingFontFaces();
243 void ParseFontShorthandForMatching(const nsACString
& aFont
,
244 StyleFontFamilyList
& aFamilyList
,
245 FontWeight
& aWeight
, FontStretch
& aStretch
,
246 FontSlantStyle
& aStyle
, ErrorResult
& aRv
);
248 virtual TimeStamp
GetNavigationStartTimeStamp() = 0;
250 mutable RecursiveMutex mMutex
;
252 FontFaceSet
* MOZ_NON_OWNING_REF mOwner
MOZ_GUARDED_BY(mMutex
);
254 // The document's node principal, which is the principal font loads for
255 // this FontFaceSet will generally use. (This principal is not used for
256 // @font-face rules in UA and user sheets, where the principal of the
257 // sheet is used instead.)
259 // This field is used from GetStandardFontLoadPrincipal. When on a
260 // style worker thread, we use mStandardFontLoadPrincipal assuming
263 // Because mDocument's principal can change over time,
264 // its value must be updated by a call to ResetStandardFontLoadPrincipal.
265 mutable RefPtr
<gfxFontSrcPrincipal
> mStandardFontLoadPrincipal
266 MOZ_GUARDED_BY(mMutex
);
268 // Set of all loaders pointing to us. These are not strong pointers,
269 // but that's OK because nsFontFaceLoader always calls RemoveLoader on
270 // us before it dies (unless we die first).
271 nsTHashtable
<nsPtrHashKey
<nsFontFaceLoader
>> mLoaders
MOZ_GUARDED_BY(mMutex
);
273 // The non rule backed FontFace objects that have been added to this
275 nsTArray
<FontFaceRecord
> mNonRuleFaces
MOZ_GUARDED_BY(mMutex
);
277 // The overall status of the loading or loaded fonts in the FontFaceSet.
278 dom::FontFaceSetLoadStatus mStatus
MOZ_GUARDED_BY(mMutex
);
280 // A map from gfxFontFaceSrc pointer identity to whether the load is allowed
281 // by CSP or other checks. We store this here because querying CSP off the
282 // main thread is not a great idea.
284 // We could use just the pointer and use this as a hash set, but then we'd
285 // have no way to verify that we've checked all the loads we should.
286 nsTHashMap
<nsPtrHashKey
<const gfxFontFaceSrc
>, bool> mAllowedFontLoads
287 MOZ_GUARDED_BY(mMutex
);
289 // Whether mNonRuleFaces has changed since last time UpdateRules ran.
290 bool mNonRuleFacesDirty
MOZ_GUARDED_BY(mMutex
);
292 // Whether any FontFace objects in mRuleFaces or mNonRuleFaces are
293 // loading. Only valid when mHasLoadingFontFacesIsDirty is false. Don't use
294 // this variable directly; call the HasLoadingFontFaces method instead.
295 bool mHasLoadingFontFaces
MOZ_GUARDED_BY(mMutex
);
297 // This variable is only valid when mLoadingDirty is false.
298 bool mHasLoadingFontFacesIsDirty
MOZ_GUARDED_BY(mMutex
);
300 // Whether CheckLoadingFinished calls should be ignored. See comment in
301 // OnFontFaceStatusChanged.
302 bool mDelayedLoadCheck
MOZ_GUARDED_BY(mMutex
);
304 // Whether the docshell for our document indicated that loads should
308 // Whether the docshell for our document indicates that we are in private
310 bool mPrivateBrowsing
;
313 } // namespace mozilla::dom
315 #endif // !defined(mozilla_dom_FontFaceSetImpl_h)