RuleProcessorCache.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * cache of re-usable nsCSSRuleProcessors for given sets of style sheets
  7. */
  8. #ifndef mozilla_RuleProcessorCache_h
  9. #define mozilla_RuleProcessorCache_h
  10. #include "mozilla/MemoryReporting.h"
  11. #include "mozilla/StaticPtr.h"
  12. #include "nsCSSRuleProcessor.h"
  13. #include "nsExpirationTracker.h"
  14. #include "nsIMediaList.h"
  15. #include "nsIMemoryReporter.h"
  16. #include "nsTArray.h"
  17. class nsCSSRuleProcessor;
  18. namespace mozilla {
  19. class CSSStyleSheet;
  20. namespace css {
  21. class DocumentRule;
  22. } // namespace css
  23. } // namespace mozilla
  24. namespace mozilla {
  25. /**
  26. * The RuleProcessorCache is a singleton object that caches
  27. * nsCSSRuleProcessors keyed off a list of style sheets and the result of
  28. * evaluating all @-moz-documents in the style sheets. nsStyleSet gets and
  29. * puts nsCSSRuleProcessors from/to the RuleProcessorCache.
  30. *
  31. * State bits on CSSStyleSheet and nsCSSRuleProcessor track whether they are in
  32. * the RuleProcessorCache. This lets us remove them from the RuleProcessorCache
  33. * when they're going away.
  34. */
  35. class RuleProcessorCache final : public nsIMemoryReporter
  36. {
  37. NS_DECL_ISUPPORTS
  38. NS_DECL_NSIMEMORYREPORTER
  39. public:
  40. static nsCSSRuleProcessor* GetRuleProcessor(
  41. const nsTArray<CSSStyleSheet*>& aSheets,
  42. nsPresContext* aPresContext);
  43. static void PutRuleProcessor(
  44. const nsTArray<CSSStyleSheet*>& aSheets,
  45. nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
  46. const nsDocumentRuleResultCacheKey& aCacheKey,
  47. nsCSSRuleProcessor* aRuleProcessor);
  48. static void StartTracking(nsCSSRuleProcessor* aRuleProcessor);
  49. static void StopTracking(nsCSSRuleProcessor* aRuleProcessor);
  50. #ifdef DEBUG
  51. static bool HasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  52. #endif
  53. static void RemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  54. static void RemoveSheet(CSSStyleSheet* aSheet);
  55. static void Shutdown() { gShutdown = true; gRuleProcessorCache = nullptr; }
  56. size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
  57. private:
  58. class ExpirationTracker : public nsExpirationTracker<nsCSSRuleProcessor,3>
  59. {
  60. public:
  61. explicit ExpirationTracker(RuleProcessorCache* aCache)
  62. : nsExpirationTracker<nsCSSRuleProcessor,3>(
  63. 10000, "RuleProcessorCache::ExpirationTracker")
  64. , mCache(aCache) {}
  65. void RemoveObjectIfTracked(nsCSSRuleProcessor* aRuleProcessor);
  66. virtual void NotifyExpired(nsCSSRuleProcessor* aRuleProcessor) override {
  67. mCache->RemoveRuleProcessor(aRuleProcessor);
  68. }
  69. private:
  70. RuleProcessorCache* mCache;
  71. };
  72. RuleProcessorCache() : mExpirationTracker(this) {}
  73. ~RuleProcessorCache();
  74. void InitMemoryReporter();
  75. static bool EnsureGlobal();
  76. static StaticRefPtr<RuleProcessorCache> gRuleProcessorCache;
  77. static bool gShutdown;
  78. void DoRemoveSheet(CSSStyleSheet* aSheet);
  79. nsCSSRuleProcessor* DoGetRuleProcessor(
  80. const nsTArray<CSSStyleSheet*>& aSheets,
  81. nsPresContext* aPresContext);
  82. void DoPutRuleProcessor(const nsTArray<CSSStyleSheet*>& aSheets,
  83. nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
  84. const nsDocumentRuleResultCacheKey& aCacheKey,
  85. nsCSSRuleProcessor* aRuleProcessor);
  86. #ifdef DEBUG
  87. bool DoHasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  88. #endif
  89. void DoRemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
  90. void DoStartTracking(nsCSSRuleProcessor* aRuleProcessor);
  91. void DoStopTracking(nsCSSRuleProcessor* aRuleProcessor);
  92. struct DocumentEntry {
  93. nsDocumentRuleResultCacheKey mCacheKey;
  94. RefPtr<nsCSSRuleProcessor> mRuleProcessor;
  95. };
  96. struct Entry {
  97. nsTArray<CSSStyleSheet*> mSheets;
  98. nsTArray<css::DocumentRule*> mDocumentRulesInSheets;
  99. nsTArray<DocumentEntry> mDocumentEntries;
  100. };
  101. // Function object to test whether an Entry object has a given sheet
  102. // in its mSheets array. If it does, removes all of its rule processors
  103. // before returning true.
  104. struct HasSheet_ThenRemoveRuleProcessors {
  105. HasSheet_ThenRemoveRuleProcessors(RuleProcessorCache* aCache,
  106. CSSStyleSheet* aSheet)
  107. : mCache(aCache), mSheet(aSheet) {}
  108. bool operator()(Entry& aEntry) {
  109. if (aEntry.mSheets.Contains(mSheet)) {
  110. for (DocumentEntry& de : aEntry.mDocumentEntries) {
  111. de.mRuleProcessor->SetInRuleProcessorCache(false);
  112. mCache->mExpirationTracker.RemoveObjectIfTracked(de.mRuleProcessor);
  113. }
  114. return true;
  115. }
  116. return false;
  117. }
  118. RuleProcessorCache* mCache;
  119. CSSStyleSheet* mSheet;
  120. };
  121. ExpirationTracker mExpirationTracker;
  122. nsTArray<Entry> mEntries;
  123. };
  124. } // namespace mozilla
  125. #endif // mozilla_RuleProcessorCache_h