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 // or by gfxUserFontSet if it cancels the loader.
97 // It's removed from the mLoaders set.
98 void RemoveLoader(nsFontFaceLoader
* aLoader
) override
;
100 virtual bool UpdateRules(const nsTArray
<nsFontFaceRuleContainer
>& aRules
) {
101 MOZ_ASSERT_UNREACHABLE("Not implemented!");
105 // search for @font-face rule that matches a platform font entry
106 virtual StyleLockedFontFaceRule
* FindRuleForEntry(gfxFontEntry
* aFontEntry
) {
107 MOZ_ASSERT_UNREACHABLE("Not implemented!");
112 * Finds an existing entry in the user font cache or creates a new user
113 * font entry for the given FontFace object.
115 static already_AddRefed
<gfxUserFontEntry
>
116 FindOrCreateUserFontEntryFromFontFace(FontFaceImpl
* aFontFace
,
117 gfxUserFontAttributes
&& aAttr
,
121 * Notification method called by a FontFace to indicate that its loading
122 * status has changed.
124 virtual void OnFontFaceStatusChanged(FontFaceImpl
* aFontFace
);
127 * Notification method called by the nsPresContext to indicate that the
128 * refresh driver ticked and flushed style and layout.
131 virtual void DidRefresh() { MOZ_ASSERT_UNREACHABLE("Not implemented!"); }
133 virtual void FlushUserFontSet() = 0;
135 static nsPresContext
* GetPresContextFor(gfxUserFontSet
* aUserFontSet
) {
136 const auto* set
= static_cast<FontFaceSetImpl
*>(aUserFontSet
);
137 return set
? set
->GetPresContext() : nullptr;
140 virtual void RefreshStandardFontLoadPrincipal();
142 virtual dom::Document
* GetDocument() const { return nullptr; }
144 virtual already_AddRefed
<URLExtraData
> GetURLExtraData() = 0;
146 // -- Web IDL --------------------------------------------------------------
148 virtual void EnsureReady() {}
149 dom::FontFaceSetLoadStatus
Status();
151 virtual bool Add(FontFaceImpl
* aFontFace
, ErrorResult
& aRv
);
152 virtual void Clear();
153 virtual bool Delete(FontFaceImpl
* aFontFace
);
155 // For ServoStyleSet to know ahead of time whether a font is loadable.
156 virtual void CacheFontLoadability() {
157 MOZ_ASSERT_UNREACHABLE("Not implemented!");
160 virtual void MarkUserFontSetDirty() {}
163 * Checks to see whether it is time to resolve mReady and dispatch any
164 * "loadingdone" and "loadingerror" events.
166 virtual void CheckLoadingFinished();
168 virtual void FindMatchingFontFaces(const nsACString
& aFont
,
169 const nsAString
& aText
,
170 nsTArray
<FontFace
*>& aFontFaces
,
173 virtual void DispatchCheckLoadingFinishedAfterDelay();
176 ~FontFaceSetImpl() override
;
178 virtual uint64_t GetInnerWindowID() = 0;
181 * Returns whether the given FontFace is currently "in" the FontFaceSet.
183 bool HasAvailableFontFace(FontFaceImpl
* aFontFace
);
186 * Returns whether there might be any pending font loads, which should cause
187 * the mReady Promise not to be resolved yet.
189 virtual bool MightHavePendingFontLoads();
192 * Checks to see whether it is time to replace mReady and dispatch a
195 void CheckLoadingStarted();
198 * Callback for invoking CheckLoadingFinished after going through the
199 * event loop. See OnFontFaceStatusChanged.
201 void CheckLoadingFinishedAfterDelay();
203 void OnLoadingStarted();
204 void OnLoadingFinished();
206 // Note: if you add new cycle collected objects to FontFaceRecord,
207 // make sure to update FontFaceSet's cycle collection macros
209 struct FontFaceRecord
{
210 RefPtr
<FontFaceImpl
> mFontFace
;
211 Maybe
<StyleOrigin
> mOrigin
; // only relevant for mRuleFaces entries
214 // search for @font-face rule that matches a userfont font entry
215 virtual StyleLockedFontFaceRule
* FindRuleForUserFontEntry(
216 gfxUserFontEntry
* aUserFontEntry
) {
220 virtual void FindMatchingFontFaces(
221 const nsTHashSet
<FontFace
*>& aMatchingFaces
,
222 nsTArray
<FontFace
*>& aFontFaces
);
224 class UpdateUserFontEntryRunnable
;
225 void UpdateUserFontEntry(gfxUserFontEntry
* aEntry
,
226 gfxUserFontAttributes
&& aAttr
);
228 nsresult
CheckFontLoad(const gfxFontFaceSrc
* aFontFaceSrc
,
229 gfxFontSrcPrincipal
** aPrincipal
, bool* aBypassCache
);
231 void InsertNonRuleFontFace(FontFaceImpl
* aFontFace
);
234 * Returns whether we have any loading FontFace objects in the FontFaceSet.
236 bool HasLoadingFontFaces();
238 // Whether mReady is pending, or would be when created.
239 bool ReadyPromiseIsPending() const;
241 // Helper function for HasLoadingFontFaces.
242 virtual void UpdateHasLoadingFontFaces();
244 void ParseFontShorthandForMatching(const nsACString
& aFont
,
245 StyleFontFamilyList
& aFamilyList
,
246 FontWeight
& aWeight
, FontStretch
& aStretch
,
247 FontSlantStyle
& aStyle
, ErrorResult
& aRv
);
249 virtual TimeStamp
GetNavigationStartTimeStamp() = 0;
251 FontFaceSet
* MOZ_NON_OWNING_REF mOwner
MOZ_GUARDED_BY(mMutex
);
253 // The document's node principal, which is the principal font loads for
254 // this FontFaceSet will generally use. (This principal is not used for
255 // @font-face rules in UA and user sheets, where the principal of the
256 // sheet is used instead.)
258 // This field is used from GetStandardFontLoadPrincipal. When on a
259 // style worker thread, we use mStandardFontLoadPrincipal assuming
262 // Because mDocument's principal can change over time,
263 // its value must be updated by a call to ResetStandardFontLoadPrincipal.
264 mutable RefPtr
<gfxFontSrcPrincipal
> mStandardFontLoadPrincipal
265 MOZ_GUARDED_BY(mMutex
);
267 // Set of all loaders pointing to us. These are not strong pointers,
268 // but that's OK because nsFontFaceLoader always calls RemoveLoader on
269 // us before it dies (unless we die first).
270 nsTHashtable
<nsPtrHashKey
<nsFontFaceLoader
>> mLoaders
MOZ_GUARDED_BY(mMutex
);
272 // The non rule backed FontFace objects that have been added to this
274 nsTArray
<FontFaceRecord
> mNonRuleFaces
MOZ_GUARDED_BY(mMutex
);
276 // The overall status of the loading or loaded fonts in the FontFaceSet.
277 dom::FontFaceSetLoadStatus mStatus
MOZ_GUARDED_BY(mMutex
);
279 // A map from gfxFontFaceSrc pointer identity to whether the load is allowed
280 // by CSP or other checks. We store this here because querying CSP off the
281 // main thread is not a great idea.
283 // We could use just the pointer and use this as a hash set, but then we'd
284 // have no way to verify that we've checked all the loads we should.
285 nsTHashMap
<nsPtrHashKey
<const gfxFontFaceSrc
>, bool> mAllowedFontLoads
286 MOZ_GUARDED_BY(mMutex
);
288 // Whether mNonRuleFaces has changed since last time UpdateRules ran.
289 bool mNonRuleFacesDirty
MOZ_GUARDED_BY(mMutex
);
291 // Whether any FontFace objects in mRuleFaces or mNonRuleFaces are
292 // loading. Only valid when mHasLoadingFontFacesIsDirty is false. Don't use
293 // this variable directly; call the HasLoadingFontFaces method instead.
294 bool mHasLoadingFontFaces
MOZ_GUARDED_BY(mMutex
);
296 // This variable is only valid when mLoadingDirty is false.
297 bool mHasLoadingFontFacesIsDirty
MOZ_GUARDED_BY(mMutex
);
299 // Whether CheckLoadingFinished calls should be ignored. See comment in
300 // OnFontFaceStatusChanged.
301 bool mDelayedLoadCheck
MOZ_GUARDED_BY(mMutex
);
303 // Whether the docshell for our document indicated that loads should
307 // Whether the docshell for our document indicates that we are in private
309 bool mPrivateBrowsing
;
312 } // namespace mozilla::dom
314 #endif // !defined(mozilla_dom_FontFaceSetImpl_h)