Line data Source code
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 : /*
8 : * cache of re-usable nsCSSRuleProcessors for given sets of style sheets
9 : */
10 :
11 : #ifndef mozilla_RuleProcessorCache_h
12 : #define mozilla_RuleProcessorCache_h
13 :
14 : #include "mozilla/MemoryReporting.h"
15 : #include "mozilla/StaticPtr.h"
16 : #include "nsCSSRuleProcessor.h"
17 : #include "nsExpirationTracker.h"
18 : #include "nsMediaList.h"
19 : #include "nsIMemoryReporter.h"
20 : #include "nsTArray.h"
21 :
22 : class nsCSSRuleProcessor;
23 : namespace mozilla {
24 : class CSSStyleSheet;
25 : namespace css {
26 : class DocumentRule;
27 : } // namespace css
28 : } // namespace mozilla
29 :
30 : namespace mozilla {
31 :
32 : /**
33 : * The RuleProcessorCache is a singleton object that caches
34 : * nsCSSRuleProcessors keyed off a list of style sheets and the result of
35 : * evaluating all @-moz-documents in the style sheets. nsStyleSet gets and
36 : * puts nsCSSRuleProcessors from/to the RuleProcessorCache.
37 : *
38 : * State bits on CSSStyleSheet and nsCSSRuleProcessor track whether they are in
39 : * the RuleProcessorCache. This lets us remove them from the RuleProcessorCache
40 : * when they're going away.
41 : */
42 : class RuleProcessorCache final : public nsIMemoryReporter
43 : {
44 : NS_DECL_ISUPPORTS
45 : NS_DECL_NSIMEMORYREPORTER
46 :
47 : public:
48 : static nsCSSRuleProcessor* GetRuleProcessor(
49 : const nsTArray<CSSStyleSheet*>& aSheets,
50 : nsPresContext* aPresContext);
51 : static void PutRuleProcessor(
52 : const nsTArray<CSSStyleSheet*>& aSheets,
53 : nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
54 : const nsDocumentRuleResultCacheKey& aCacheKey,
55 : nsCSSRuleProcessor* aRuleProcessor);
56 : static void StartTracking(nsCSSRuleProcessor* aRuleProcessor);
57 : static void StopTracking(nsCSSRuleProcessor* aRuleProcessor);
58 :
59 : #ifdef DEBUG
60 : static bool HasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
61 : #endif
62 : static void RemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
63 : static void RemoveSheet(CSSStyleSheet* aSheet);
64 :
65 0 : static void Shutdown() { gShutdown = true; gRuleProcessorCache = nullptr; }
66 :
67 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
68 :
69 : private:
70 0 : class ExpirationTracker : public nsExpirationTracker<nsCSSRuleProcessor,3>
71 : {
72 : public:
73 2 : explicit ExpirationTracker(RuleProcessorCache* aCache)
74 2 : : nsExpirationTracker<nsCSSRuleProcessor,3>(
75 : 10000, "RuleProcessorCache::ExpirationTracker",
76 2 : SystemGroup::EventTargetFor(TaskCategory::Other))
77 2 : , mCache(aCache) {}
78 :
79 : void RemoveObjectIfTracked(nsCSSRuleProcessor* aRuleProcessor);
80 :
81 0 : virtual void NotifyExpired(nsCSSRuleProcessor* aRuleProcessor) override {
82 0 : mCache->RemoveRuleProcessor(aRuleProcessor);
83 0 : }
84 :
85 : private:
86 : RuleProcessorCache* mCache;
87 : };
88 :
89 2 : RuleProcessorCache() : mExpirationTracker(this) {}
90 : ~RuleProcessorCache();
91 :
92 : void InitMemoryReporter();
93 :
94 : static bool EnsureGlobal();
95 : static StaticRefPtr<RuleProcessorCache> gRuleProcessorCache;
96 : static bool gShutdown;
97 :
98 : void DoRemoveSheet(CSSStyleSheet* aSheet);
99 : nsCSSRuleProcessor* DoGetRuleProcessor(
100 : const nsTArray<CSSStyleSheet*>& aSheets,
101 : nsPresContext* aPresContext);
102 : void DoPutRuleProcessor(const nsTArray<CSSStyleSheet*>& aSheets,
103 : nsTArray<css::DocumentRule*>&& aDocumentRulesInSheets,
104 : const nsDocumentRuleResultCacheKey& aCacheKey,
105 : nsCSSRuleProcessor* aRuleProcessor);
106 : #ifdef DEBUG
107 : bool DoHasRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
108 : #endif
109 : void DoRemoveRuleProcessor(nsCSSRuleProcessor* aRuleProcessor);
110 : void DoStartTracking(nsCSSRuleProcessor* aRuleProcessor);
111 : void DoStopTracking(nsCSSRuleProcessor* aRuleProcessor);
112 :
113 10 : struct DocumentEntry {
114 : nsDocumentRuleResultCacheKey mCacheKey;
115 : RefPtr<nsCSSRuleProcessor> mRuleProcessor;
116 : };
117 :
118 10 : struct Entry {
119 : nsTArray<CSSStyleSheet*> mSheets;
120 : nsTArray<css::DocumentRule*> mDocumentRulesInSheets;
121 : nsTArray<DocumentEntry> mDocumentEntries;
122 : };
123 :
124 : // Function object to test whether an Entry object has a given sheet
125 : // in its mSheets array. If it does, removes all of its rule processors
126 : // before returning true.
127 : struct HasSheet_ThenRemoveRuleProcessors {
128 0 : HasSheet_ThenRemoveRuleProcessors(RuleProcessorCache* aCache,
129 : CSSStyleSheet* aSheet)
130 0 : : mCache(aCache), mSheet(aSheet) {}
131 0 : bool operator()(Entry& aEntry) {
132 0 : if (aEntry.mSheets.Contains(mSheet)) {
133 0 : for (DocumentEntry& de : aEntry.mDocumentEntries) {
134 0 : de.mRuleProcessor->SetInRuleProcessorCache(false);
135 0 : mCache->mExpirationTracker.RemoveObjectIfTracked(de.mRuleProcessor);
136 : }
137 0 : return true;
138 : }
139 0 : return false;
140 : }
141 : RuleProcessorCache* mCache;
142 : CSSStyleSheet* mSheet;
143 : };
144 :
145 : ExpirationTracker mExpirationTracker;
146 : nsTArray<Entry> mEntries;
147 : };
148 :
149 : } // namespace mozilla
150 :
151 : #endif // mozilla_RuleProcessorCache_h
|