Bug 1700051: part 35) Reduce accessibility of `mSoftText.mDOMMapping` to `private...
[gecko.git] / layout / style / FontFaceSet.h
blob24f21f087fd6bf287d44ed62bb8784d01e514c47
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_FontFaceSet_h
8 #define mozilla_dom_FontFaceSet_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 "gfxUserFontSet.h"
15 #include "nsICSSLoaderObserver.h"
16 #include "nsIDOMEventListener.h"
18 struct gfxFontFaceSrc;
19 class gfxFontSrcPrincipal;
20 class gfxUserFontEntry;
21 class nsFontFaceLoader;
22 class nsIPrincipal;
23 class nsPIDOMWindowInner;
24 struct RawServoFontFaceRule;
26 namespace mozilla {
27 class PostTraversalTask;
28 class SharedFontList;
29 namespace dom {
30 class FontFace;
31 class Promise;
32 } // namespace dom
33 } // namespace mozilla
35 namespace mozilla {
36 namespace dom {
38 class FontFaceSet final : public DOMEventTargetHelper,
39 public nsIDOMEventListener,
40 public nsICSSLoaderObserver {
41 friend class mozilla::PostTraversalTask;
42 friend class UserFontSet;
44 public:
45 /**
46 * A gfxUserFontSet that integrates with the layout and style systems to
47 * manage @font-face rules and handle network requests for font loading.
49 * We would combine this class and FontFaceSet into the one class if it were
50 * possible; it's not because FontFaceSet is cycle collected and
51 * gfxUserFontSet isn't (and can't be, as gfx classes don't use the cycle
52 * collector). So UserFontSet exists just to override the needed virtual
53 * methods from gfxUserFontSet and to forward them on FontFaceSet.
55 class UserFontSet final : public gfxUserFontSet {
56 friend class FontFaceSet;
58 public:
59 explicit UserFontSet(FontFaceSet* aFontFaceSet)
60 : mFontFaceSet(aFontFaceSet) {}
62 FontFaceSet* GetFontFaceSet() { return mFontFaceSet; }
64 gfxFontSrcPrincipal* GetStandardFontLoadPrincipal() const final {
65 return mFontFaceSet ? mFontFaceSet->mStandardFontLoadPrincipal.get()
66 : nullptr;
69 bool IsFontLoadAllowed(const gfxFontFaceSrc&) final;
71 void DispatchFontLoadViolations(
72 nsTArray<nsCOMPtr<nsIRunnable>>& aViolations) override;
74 virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
75 uint32_t aSrcIndex) override;
77 void RecordFontLoadDone(uint32_t aFontSize, TimeStamp aDoneTime) override;
79 bool BypassCache() final {
80 return mFontFaceSet && mFontFaceSet->mBypassCache;
83 protected:
84 virtual bool GetPrivateBrowsing() override;
85 virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
86 const gfxFontFaceSrc* aFontFaceSrc,
87 uint8_t*& aBuffer,
88 uint32_t& aBufferLength) override;
89 virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
90 uint32_t aSrcIndex, const char* aMessage,
91 uint32_t aFlags = nsIScriptError::errorFlag,
92 nsresult aStatus = NS_OK) override;
93 virtual void DoRebuildUserFontSet() override;
94 already_AddRefed<gfxUserFontEntry> CreateUserFontEntry(
95 const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, WeightRange aWeight,
96 StretchRange aStretch, SlantStyleRange aStyle,
97 const nsTArray<gfxFontFeature>& aFeatureSettings,
98 const nsTArray<gfxFontVariation>& aVariationSettings,
99 uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges,
100 StyleFontDisplay aFontDisplay, RangeFlags aRangeFlags,
101 float aAscentOverride, float aDescentOverride, float aLineGapOverride,
102 float aSizeAdjust) override;
104 private:
105 RefPtr<FontFaceSet> mFontFaceSet;
108 NS_DECL_ISUPPORTS_INHERITED
109 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FontFaceSet, DOMEventTargetHelper)
110 NS_DECL_NSIDOMEVENTLISTENER
112 FontFaceSet(nsPIDOMWindowInner* aWindow, dom::Document* aDocument);
114 virtual JSObject* WrapObject(JSContext* aCx,
115 JS::Handle<JSObject*> aGivenProto) override;
117 UserFontSet* GetUserFontSet() { return mUserFontSet; }
119 // Called by nsFontFaceLoader when the loader has completed normally.
120 // It's removed from the mLoaders set.
121 void RemoveLoader(nsFontFaceLoader* aLoader);
123 bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);
125 nsPresContext* GetPresContext();
127 // search for @font-face rule that matches a platform font entry
128 RawServoFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry);
130 void IncrementGeneration(bool aIsRebuild = false);
133 * Finds an existing entry in the user font cache or creates a new user
134 * font entry for the given FontFace object.
136 static already_AddRefed<gfxUserFontEntry>
137 FindOrCreateUserFontEntryFromFontFace(FontFace* aFontFace);
140 * Notification method called by a FontFace to indicate that its loading
141 * status has changed.
143 void OnFontFaceStatusChanged(FontFace* aFontFace);
146 * Notification method called by the nsPresContext to indicate that the
147 * refresh driver ticked and flushed style and layout.
148 * were just flushed.
150 void DidRefresh();
153 * Returns whether the "layout.css.font-loading-api.enabled" pref is true.
155 static bool PrefEnabled();
157 // nsICSSLoaderObserver
158 NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
159 nsresult aStatus) override;
161 FontFace* GetFontFaceAt(uint32_t aIndex);
163 void FlushUserFontSet();
165 static nsPresContext* GetPresContextFor(gfxUserFontSet* aUserFontSet) {
166 FontFaceSet* set = static_cast<UserFontSet*>(aUserFontSet)->mFontFaceSet;
167 return set ? set->GetPresContext() : nullptr;
170 void RefreshStandardFontLoadPrincipal();
172 void CopyNonRuleFacesTo(FontFaceSet* aFontFaceSet) const;
174 dom::Document* Document() const { return mDocument; }
176 // -- Web IDL --------------------------------------------------------------
178 IMPL_EVENT_HANDLER(loading)
179 IMPL_EVENT_HANDLER(loadingdone)
180 IMPL_EVENT_HANDLER(loadingerror)
181 already_AddRefed<dom::Promise> Load(JSContext* aCx, const nsACString& aFont,
182 const nsAString& aText, ErrorResult& aRv);
183 bool Check(const nsACString& aFont, const nsAString& aText, ErrorResult& aRv);
184 dom::Promise* GetReady(ErrorResult& aRv);
185 dom::FontFaceSetLoadStatus Status();
187 void Add(FontFace& aFontFace, ErrorResult& aRv);
188 void Clear();
189 bool Delete(FontFace& aFontFace);
190 bool Has(FontFace& aFontFace);
191 uint32_t Size();
192 already_AddRefed<dom::FontFaceSetIterator> Entries();
193 already_AddRefed<dom::FontFaceSetIterator> Values();
194 MOZ_CAN_RUN_SCRIPT
195 void ForEach(JSContext* aCx, FontFaceSetForEachCallback& aCallback,
196 JS::Handle<JS::Value> aThisArg, ErrorResult& aRv);
198 // For ServoStyleSet to know ahead of time whether a font is loadable.
199 void CacheFontLoadability();
201 void MarkUserFontSetDirty();
203 private:
204 ~FontFaceSet();
207 * Returns whether the given FontFace is currently "in" the FontFaceSet.
209 bool HasAvailableFontFace(FontFace* aFontFace);
212 * Removes any listeners and observers.
214 void Disconnect();
216 void RemoveDOMContentLoadedListener();
219 * Returns whether there might be any pending font loads, which should cause
220 * the mReady Promise not to be resolved yet.
222 bool MightHavePendingFontLoads();
225 * Checks to see whether it is time to replace mReady and dispatch a
226 * "loading" event.
228 void CheckLoadingStarted();
231 * Checks to see whether it is time to resolve mReady and dispatch any
232 * "loadingdone" and "loadingerror" events.
234 void CheckLoadingFinished();
237 * Callback for invoking CheckLoadingFinished after going through the
238 * event loop. See OnFontFaceStatusChanged.
240 void CheckLoadingFinishedAfterDelay();
243 * Dispatches a FontFaceSetLoadEvent to this object.
245 void DispatchLoadingFinishedEvent(
246 const nsAString& aType, nsTArray<OwningNonNull<FontFace>>&& aFontFaces);
248 // Note: if you add new cycle collected objects to FontFaceRecord,
249 // make sure to update FontFaceSet's cycle collection macros
250 // accordingly.
251 struct FontFaceRecord {
252 RefPtr<FontFace> mFontFace;
253 Maybe<StyleOrigin> mOrigin; // only relevant for mRuleFaces entries
255 // When true, indicates that when finished loading, the FontFace should be
256 // included in the subsequent loadingdone/loadingerror event fired at the
257 // FontFaceSet.
258 bool mLoadEventShouldFire;
261 static already_AddRefed<gfxUserFontEntry>
262 FindOrCreateUserFontEntryFromFontFace(const nsACString& aFamilyName,
263 FontFace* aFontFace, StyleOrigin);
265 // search for @font-face rule that matches a userfont font entry
266 RawServoFontFaceRule* FindRuleForUserFontEntry(
267 gfxUserFontEntry* aUserFontEntry);
269 nsresult StartLoad(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex);
270 gfxFontSrcPrincipal* GetStandardFontLoadPrincipal();
271 nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
272 gfxFontSrcPrincipal** aPrincipal, bool* aBypassCache);
273 bool IsFontLoadAllowed(const gfxFontFaceSrc& aSrc);
275 void DispatchFontLoadViolations(nsTArray<nsCOMPtr<nsIRunnable>>& aViolations);
276 nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
277 const gfxFontFaceSrc* aFontFaceSrc,
278 uint8_t*& aBuffer, uint32_t& aBufferLength);
279 nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex,
280 const char* aMessage, uint32_t aFlags, nsresult aStatus);
282 void InsertRuleFontFace(FontFace* aFontFace, StyleOrigin aOrigin,
283 nsTArray<FontFaceRecord>& aOldRecords,
284 bool& aFontSetModified);
285 void InsertNonRuleFontFace(FontFace* aFontFace, bool& aFontSetModified);
287 #ifdef DEBUG
288 bool HasRuleFontFace(FontFace* aFontFace);
289 #endif
292 * Returns whether we have any loading FontFace objects in the FontFaceSet.
294 bool HasLoadingFontFaces();
296 // Whether mReady is pending, or would be when created.
297 bool ReadyPromiseIsPending() const;
299 // Helper function for HasLoadingFontFaces.
300 void UpdateHasLoadingFontFaces();
302 void ParseFontShorthandForMatching(const nsACString& aFont,
303 RefPtr<SharedFontList>& aFamilyList,
304 FontWeight& aWeight, FontStretch& aStretch,
305 FontSlantStyle& aStyle, ErrorResult& aRv);
306 void FindMatchingFontFaces(const nsACString& aFont, const nsAString& aText,
307 nsTArray<FontFace*>& aFontFaces, ErrorResult& aRv);
309 void DispatchLoadingEventAndReplaceReadyPromise();
310 void DispatchCheckLoadingFinishedAfterDelay();
312 TimeStamp GetNavigationStartTimeStamp();
314 RefPtr<UserFontSet> mUserFontSet;
316 // The document this is a FontFaceSet for.
317 RefPtr<dom::Document> mDocument;
319 // The document's node principal, which is the principal font loads for
320 // this FontFaceSet will generally use. (This principal is not used for
321 // @font-face rules in UA and user sheets, where the principal of the
322 // sheet is used instead.)
324 // This field is used from GetStandardFontLoadPrincipal. When on a
325 // style worker thread, we use mStandardFontLoadPrincipal assuming
326 // it is up to date.
328 // Because mDocument's principal can change over time,
329 // its value must be updated by a call to ResetStandardFontLoadPrincipal.
330 RefPtr<gfxFontSrcPrincipal> mStandardFontLoadPrincipal;
332 // A Promise that is fulfilled once all of the FontFace objects
333 // in mRuleFaces and mNonRuleFaces that started or were loading at the
334 // time the Promise was created have finished loading. It is rejected if
335 // any of those fonts failed to load. mReady is replaced with
336 // a new Promise object whenever mReady is settled and another
337 // FontFace in mRuleFaces or mNonRuleFaces starts to load.
338 // Note that mReady is created lazily when GetReady() is called.
339 RefPtr<dom::Promise> mReady;
340 // Whether the ready promise must be resolved when it's created.
341 bool mResolveLazilyCreatedReadyPromise;
343 // Set of all loaders pointing to us. These are not strong pointers,
344 // but that's OK because nsFontFaceLoader always calls RemoveLoader on
345 // us before it dies (unless we die first).
346 nsTHashtable<nsPtrHashKey<nsFontFaceLoader>> mLoaders;
348 // The @font-face rule backed FontFace objects in the FontFaceSet.
349 nsTArray<FontFaceRecord> mRuleFaces;
351 // The non rule backed FontFace objects that have been added to this
352 // FontFaceSet.
353 nsTArray<FontFaceRecord> mNonRuleFaces;
355 // The overall status of the loading or loaded fonts in the FontFaceSet.
356 dom::FontFaceSetLoadStatus mStatus;
358 // A map from gfxFontFaceSrc pointer identity to whether the load is allowed
359 // by CSP or other checks. We store this here because querying CSP off the
360 // main thread is not a great idea.
362 // We could use just the pointer and use this as a hash set, but then we'd
363 // have no way to verify that we've checked all the loads we should.
364 nsTHashMap<nsPtrHashKey<const gfxFontFaceSrc>, bool> mAllowedFontLoads;
366 // Whether mNonRuleFaces has changed since last time UpdateRules ran.
367 bool mNonRuleFacesDirty;
369 // Whether any FontFace objects in mRuleFaces or mNonRuleFaces are
370 // loading. Only valid when mHasLoadingFontFacesIsDirty is false. Don't use
371 // this variable directly; call the HasLoadingFontFaces method instead.
372 bool mHasLoadingFontFaces;
374 // This variable is only valid when mLoadingDirty is false.
375 bool mHasLoadingFontFacesIsDirty;
377 // Whether CheckLoadingFinished calls should be ignored. See comment in
378 // OnFontFaceStatusChanged.
379 bool mDelayedLoadCheck;
381 // Whether the docshell for our document indicated that loads should
382 // bypass the cache.
383 bool mBypassCache;
385 // Whether the docshell for our document indicates that we are in private
386 // browsing mode.
387 bool mPrivateBrowsing;
390 } // namespace dom
391 } // namespace mozilla
393 #endif // !defined(mozilla_dom_FontFaceSet_h)