FontFaceSetImpl.h (10851B)
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/. */ 6 7 #ifndef mozilla_dom_FontFaceSetImpl_h 8 #define mozilla_dom_FontFaceSetImpl_h 9 10 #include <functional> 11 12 #include "gfxUserFontSet.h" 13 #include "mozilla/DOMEventTargetHelper.h" 14 #include "mozilla/FontPropertyTypes.h" 15 #include "mozilla/RecursiveMutex.h" 16 #include "mozilla/dom/FontFace.h" 17 #include "mozilla/dom/FontFaceSetBinding.h" 18 #include "nsICSSLoaderObserver.h" 19 #include "nsIDOMEventListener.h" 20 21 struct gfxFontFaceSrc; 22 class gfxFontSrcPrincipal; 23 class gfxUserFontEntry; 24 class nsFontFaceLoader; 25 class nsIChannel; 26 class nsIPrincipal; 27 class nsPIDOMWindowInner; 28 29 namespace mozilla { 30 struct StyleLockedFontFaceRule; 31 class PostTraversalTask; 32 class Runnable; 33 class SharedFontList; 34 namespace dom { 35 class FontFace; 36 } // namespace dom 37 } // namespace mozilla 38 39 namespace mozilla::dom { 40 41 class FontFaceSetImpl : public nsISupports, public gfxUserFontSet { 42 NS_DECL_THREADSAFE_ISUPPORTS 43 44 public: 45 // gfxUserFontSet 46 47 already_AddRefed<gfxFontSrcPrincipal> GetStandardFontLoadPrincipal() 48 const final; 49 50 void RecordFontLoadDone(uint32_t aFontSize, TimeStamp aDoneTime) override; 51 52 bool BypassCache() final { return mBypassCache; } 53 54 void ForgetLocalFaces() final; 55 56 protected: 57 virtual nsresult CreateChannelForSyncLoadFontData( 58 nsIChannel** aOutChannel, gfxUserFontEntry* aFontToLoad, 59 const gfxFontFaceSrc* aFontFaceSrc) = 0; 60 61 // gfxUserFontSet 62 63 bool GetPrivateBrowsing() override { return mPrivateBrowsing; } 64 nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad, 65 const gfxFontFaceSrc* aFontFaceSrc, 66 uint8_t*& aBuffer, 67 uint32_t& aBufferLength) override; 68 nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, uint32_t aSrcIndex, 69 const char* aMessage, 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; 76 77 already_AddRefed<gfxUserFontFamily> GetFamily( 78 const nsACString& aFamilyName) final; 79 80 explicit FontFaceSetImpl(FontFaceSet* aOwner); 81 82 void DestroyLoaders(); 83 84 public: 85 virtual void Destroy(); 86 virtual bool IsOnOwningThread() = 0; 87 #ifdef DEBUG 88 virtual void AssertIsOnOwningThread() = 0; 89 #else 90 void AssertIsOnOwningThread() {} 91 #endif 92 virtual void DispatchToOwningThread(const char* aName, 93 std::function<void()>&& aFunc) = 0; 94 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; 99 100 virtual bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules) { 101 MOZ_ASSERT_UNREACHABLE("Not implemented!"); 102 return false; 103 } 104 105 // search for @font-face rule that matches a platform font entry 106 virtual StyleLockedFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry) { 107 MOZ_ASSERT_UNREACHABLE("Not implemented!"); 108 return nullptr; 109 } 110 111 /** 112 * Finds an existing entry in the user font cache or creates a new user 113 * font entry for the given FontFace object. 114 */ 115 static already_AddRefed<gfxUserFontEntry> 116 FindOrCreateUserFontEntryFromFontFace(FontFaceImpl* aFontFace, 117 gfxUserFontAttributes&& aAttr, 118 StyleOrigin); 119 120 /** 121 * Notification method called by a FontFace to indicate that its loading 122 * status has changed. 123 */ 124 virtual void OnFontFaceStatusChanged(FontFaceImpl* aFontFace); 125 126 /** 127 * Notification method called by the nsPresContext to indicate that the 128 * refresh driver ticked and flushed style and layout. 129 * were just flushed. 130 */ 131 virtual void DidRefresh() { MOZ_ASSERT_UNREACHABLE("Not implemented!"); } 132 133 virtual void FlushUserFontSet() = 0; 134 135 static FontVisibilityProvider* GetFontVisibilityProviderFor( 136 gfxUserFontSet* aUserFontSet) { 137 const auto* set = static_cast<FontFaceSetImpl*>(aUserFontSet); 138 return set ? set->GetFontVisibilityProvider() : nullptr; 139 } 140 141 virtual void RefreshStandardFontLoadPrincipal(); 142 143 virtual dom::Document* GetDocument() const { return nullptr; } 144 145 virtual already_AddRefed<URLExtraData> GetURLExtraData() = 0; 146 147 // -- Web IDL -------------------------------------------------------------- 148 149 virtual void EnsureReady() {} 150 dom::FontFaceSetLoadStatus Status(); 151 152 virtual bool Add(FontFaceImpl* aFontFace, ErrorResult& aRv); 153 virtual void Clear(); 154 virtual bool Delete(FontFaceImpl* aFontFace); 155 156 // For ServoStyleSet to know ahead of time whether a font is loadable. 157 virtual void CacheFontLoadability() { 158 MOZ_ASSERT_UNREACHABLE("Not implemented!"); 159 } 160 161 virtual void MarkUserFontSetDirty() {} 162 163 /** 164 * Checks to see whether it is time to resolve mReady and dispatch any 165 * "loadingdone" and "loadingerror" events. 166 */ 167 virtual void CheckLoadingFinished(); 168 169 virtual void FindMatchingFontFaces(const nsACString& aFont, 170 const nsAString& aText, 171 nsTArray<FontFace*>& aFontFaces, 172 ErrorResult& aRv); 173 174 virtual void DispatchCheckLoadingFinishedAfterDelay(); 175 176 protected: 177 ~FontFaceSetImpl() override; 178 179 virtual uint64_t GetInnerWindowID() = 0; 180 181 /** 182 * Returns whether the given FontFace is currently "in" the FontFaceSet. 183 */ 184 bool HasAvailableFontFace(FontFaceImpl* aFontFace); 185 186 /** 187 * Returns whether there might be any pending font loads, which should cause 188 * the mReady Promise not to be resolved yet. 189 */ 190 virtual bool MightHavePendingFontLoads(); 191 192 /** 193 * Checks to see whether it is time to replace mReady and dispatch a 194 * "loading" event. 195 */ 196 void CheckLoadingStarted(); 197 198 /** 199 * Callback for invoking CheckLoadingFinished after going through the 200 * event loop. See OnFontFaceStatusChanged. 201 */ 202 void CheckLoadingFinishedAfterDelay(); 203 204 void OnLoadingStarted(); 205 void OnLoadingFinished(); 206 207 // Note: if you add new cycle collected objects to FontFaceRecord, 208 // make sure to update FontFaceSet's cycle collection macros 209 // accordingly. 210 struct FontFaceRecord { 211 RefPtr<FontFaceImpl> mFontFace; 212 Maybe<StyleOrigin> mOrigin; // only relevant for mRuleFaces entries 213 }; 214 215 // search for @font-face rule that matches a userfont font entry 216 virtual StyleLockedFontFaceRule* FindRuleForUserFontEntry( 217 gfxUserFontEntry* aUserFontEntry) { 218 return nullptr; 219 } 220 221 virtual void FindMatchingFontFaces( 222 const nsTHashSet<FontFace*>& aMatchingFaces, 223 nsTArray<FontFace*>& aFontFaces); 224 225 class UpdateUserFontEntryRunnable; 226 void UpdateUserFontEntry(gfxUserFontEntry* aEntry, 227 gfxUserFontAttributes&& aAttr); 228 229 nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc, 230 gfxFontSrcPrincipal** aPrincipal, bool* aBypassCache); 231 232 void InsertNonRuleFontFace(FontFaceImpl* aFontFace); 233 234 /** 235 * Returns whether we have any loading FontFace objects in the FontFaceSet. 236 */ 237 bool HasLoadingFontFaces(); 238 239 // Whether mReady is pending, or would be when created. 240 bool ReadyPromiseIsPending() const; 241 242 // Helper function for HasLoadingFontFaces. 243 virtual void UpdateHasLoadingFontFaces(); 244 245 void ParseFontShorthandForMatching(const nsACString& aFont, 246 StyleFontFamilyList& aFamilyList, 247 FontWeight& aWeight, FontStretch& aStretch, 248 FontSlantStyle& aStyle, ErrorResult& aRv); 249 250 virtual TimeStamp GetNavigationStartTimeStamp() = 0; 251 252 FontFaceSet* MOZ_NON_OWNING_REF mOwner MOZ_GUARDED_BY(mMutex); 253 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.) 258 // 259 // This field is used from GetStandardFontLoadPrincipal. When on a 260 // style worker thread, we use mStandardFontLoadPrincipal assuming 261 // it is up to date. 262 // 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); 267 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); 272 273 // The non rule backed FontFace objects that have been added to this 274 // FontFaceSet. 275 nsTArray<FontFaceRecord> mNonRuleFaces MOZ_GUARDED_BY(mMutex); 276 277 // The overall status of the loading or loaded fonts in the FontFaceSet. 278 dom::FontFaceSetLoadStatus mStatus MOZ_GUARDED_BY(mMutex); 279 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. 283 // 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); 288 289 // Whether mNonRuleFaces has changed since last time UpdateRules ran. 290 bool mNonRuleFacesDirty MOZ_GUARDED_BY(mMutex); 291 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); 296 297 // This variable is only valid when mLoadingDirty is false. 298 bool mHasLoadingFontFacesIsDirty MOZ_GUARDED_BY(mMutex); 299 300 // Whether CheckLoadingFinished calls should be ignored. See comment in 301 // OnFontFaceStatusChanged. 302 bool mDelayedLoadCheck MOZ_GUARDED_BY(mMutex); 303 304 // Whether the docshell for our document indicated that loads should 305 // bypass the cache. 306 bool mBypassCache; 307 308 // Whether the docshell for our document indicates that we are in private 309 // browsing mode. 310 bool mPrivateBrowsing; 311 }; 312 313 } // namespace mozilla::dom 314 315 #endif // !defined(mozilla_dom_FontFaceSetImpl_h)