1 | /* |
2 | Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
3 | Copyright (C) 2001 Dirk Mueller <mueller@kde.org> |
4 | Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | |
21 | This class provides all functionality needed for loading images, style sheets and html |
22 | pages from the web. It has a memory cache for these objects. |
23 | */ |
24 | |
25 | #pragma once |
26 | |
27 | #include "NativeImage.h" |
28 | #include "SecurityOriginHash.h" |
29 | #include "Timer.h" |
30 | #include <pal/SessionID.h> |
31 | #include <wtf/Forward.h> |
32 | #include <wtf/Function.h> |
33 | #include <wtf/HashMap.h> |
34 | #include <wtf/HashSet.h> |
35 | #include <wtf/ListHashSet.h> |
36 | #include <wtf/Noncopyable.h> |
37 | #include <wtf/Vector.h> |
38 | #include <wtf/text/StringHash.h> |
39 | #include <wtf/text/WTFString.h> |
40 | |
41 | namespace WebCore { |
42 | |
43 | class CachedResource; |
44 | class CookieJar; |
45 | class ResourceRequest; |
46 | class ResourceResponse; |
47 | class ScriptExecutionContext; |
48 | class SecurityOrigin; |
49 | |
50 | // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc. |
51 | |
52 | // The cache keeps a flexible but bounded window of dead resources that grows/shrinks |
53 | // depending on the live resource load. Here's an example of cache growth over time, |
54 | // with a min dead resource capacity of 25% and a max dead resource capacity of 50%: |
55 | |
56 | // |-----| Dead: - |
57 | // |----------| Live: + |
58 | // --|----------| Cache boundary: | (objects outside this mark have been evicted) |
59 | // --|----------++++++++++| |
60 | // -------|-----+++++++++++++++| |
61 | // -------|-----+++++++++++++++|+++++ |
62 | |
63 | class MemoryCache { |
64 | WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED; |
65 | friend NeverDestroyed<MemoryCache>; |
66 | friend class Internals; |
67 | public: |
68 | struct TypeStatistic { |
69 | int count; |
70 | int size; |
71 | int liveSize; |
72 | int decodedSize; |
73 | |
74 | TypeStatistic() |
75 | : count(0) |
76 | , size(0) |
77 | , liveSize(0) |
78 | , decodedSize(0) |
79 | { |
80 | } |
81 | |
82 | void addResource(CachedResource&); |
83 | }; |
84 | |
85 | struct Statistics { |
86 | TypeStatistic images; |
87 | TypeStatistic cssStyleSheets; |
88 | TypeStatistic scripts; |
89 | TypeStatistic xslStyleSheets; |
90 | TypeStatistic fonts; |
91 | }; |
92 | |
93 | WEBCORE_EXPORT static MemoryCache& singleton(); |
94 | |
95 | WEBCORE_EXPORT CachedResource* resourceForRequest(const ResourceRequest&, PAL::SessionID); |
96 | |
97 | bool add(CachedResource&); |
98 | void remove(CachedResource&); |
99 | |
100 | static bool shouldRemoveFragmentIdentifier(const URL&); |
101 | static URL removeFragmentIdentifierIfNeeded(const URL&); |
102 | |
103 | void revalidationSucceeded(CachedResource& revalidatingResource, const ResourceResponse&); |
104 | void revalidationFailed(CachedResource& revalidatingResource); |
105 | |
106 | void forEachResource(const WTF::Function<void(CachedResource&)>&); |
107 | void forEachSessionResource(PAL::SessionID, const WTF::Function<void(CachedResource&)>&); |
108 | WEBCORE_EXPORT void destroyDecodedDataForAllImages(); |
109 | |
110 | // Sets the cache's memory capacities, in bytes. These will hold only approximately, |
111 | // since the decoded cost of resources like scripts and stylesheets is not known. |
112 | // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure. |
113 | // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure. |
114 | // - totalBytes: The maximum number of bytes that the cache should consume overall. |
115 | WEBCORE_EXPORT void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes); |
116 | |
117 | // Turn the cache on and off. Disabling the cache will remove all resources from the cache. They may |
118 | // still live on if they are referenced by some Web page though. |
119 | WEBCORE_EXPORT void setDisabled(bool); |
120 | bool disabled() const { return m_disabled; } |
121 | |
122 | WEBCORE_EXPORT void evictResources(); |
123 | WEBCORE_EXPORT void evictResources(PAL::SessionID); |
124 | |
125 | void prune(); |
126 | void pruneSoon(); |
127 | unsigned size() const { return m_liveSize + m_deadSize; } |
128 | |
129 | void setDeadDecodedDataDeletionInterval(Seconds interval) { m_deadDecodedDataDeletionInterval = interval; } |
130 | Seconds deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; } |
131 | |
132 | // Calls to put the cached resource into and out of LRU lists. |
133 | void insertInLRUList(CachedResource&); |
134 | void removeFromLRUList(CachedResource&); |
135 | |
136 | // Called to adjust the cache totals when a resource changes size. |
137 | void adjustSize(bool live, long long delta); |
138 | |
139 | // Track decoded resources that are in the cache and referenced by a Web page. |
140 | void insertInLiveDecodedResourcesList(CachedResource&); |
141 | void removeFromLiveDecodedResourcesList(CachedResource&); |
142 | |
143 | void addToLiveResourcesSize(CachedResource&); |
144 | void removeFromLiveResourcesSize(CachedResource&); |
145 | |
146 | static void removeRequestFromSessionCaches(ScriptExecutionContext&, const ResourceRequest&); |
147 | |
148 | // Function to collect cache statistics for the caches window in the Safari Debug menu. |
149 | WEBCORE_EXPORT Statistics getStatistics(); |
150 | |
151 | void resourceAccessed(CachedResource&); |
152 | bool inLiveDecodedResourcesList(CachedResource& resource) const { return m_liveDecodedResources.contains(&resource); } |
153 | |
154 | typedef HashSet<RefPtr<SecurityOrigin>> SecurityOriginSet; |
155 | WEBCORE_EXPORT void removeResourcesWithOrigin(SecurityOrigin&); |
156 | WEBCORE_EXPORT void removeResourcesWithOrigins(PAL::SessionID, const HashSet<RefPtr<SecurityOrigin>>&); |
157 | WEBCORE_EXPORT void getOriginsWithCache(SecurityOriginSet& origins); |
158 | WEBCORE_EXPORT HashSet<RefPtr<SecurityOrigin>> originsWithCache(PAL::SessionID) const; |
159 | |
160 | WEBCORE_EXPORT bool addImageToCache(NativeImagePtr&&, const URL&, const String& domainForCachePartition, const PAL::SessionID&, const CookieJar*); |
161 | WEBCORE_EXPORT void removeImageFromCache(const URL&, const String& domainForCachePartition); |
162 | |
163 | // pruneDead*() - Flush decoded and encoded data from resources not referenced by Web pages. |
164 | // pruneLive*() - Flush decoded data from resources still referenced by Web pages. |
165 | WEBCORE_EXPORT void pruneDeadResources(); // Automatically decide how much to prune. |
166 | WEBCORE_EXPORT void pruneLiveResources(bool shouldDestroyDecodedDataForAllLiveResources = false); |
167 | |
168 | WEBCORE_EXPORT void pruneDeadResourcesToSize(unsigned targetSize); |
169 | WEBCORE_EXPORT void pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestroyDecodedDataForAllLiveResources = false); |
170 | |
171 | private: |
172 | typedef HashMap<std::pair<URL, String /* partitionName */>, CachedResource*> CachedResourceMap; |
173 | typedef ListHashSet<CachedResource*> LRUList; |
174 | |
175 | MemoryCache(); |
176 | ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. |
177 | |
178 | LRUList& lruListFor(CachedResource&); |
179 | |
180 | void dumpStats(); |
181 | void dumpLRULists(bool includeLive) const; |
182 | |
183 | unsigned liveCapacity() const; |
184 | unsigned deadCapacity() const; |
185 | bool needsPruning() const; |
186 | |
187 | CachedResource* resourceForRequestImpl(const ResourceRequest&, CachedResourceMap&); |
188 | |
189 | CachedResourceMap& ensureSessionResourceMap(PAL::SessionID); |
190 | CachedResourceMap* sessionResourceMap(PAL::SessionID) const; |
191 | |
192 | bool m_disabled { false }; |
193 | bool m_inPruneResources { false }; |
194 | |
195 | unsigned m_capacity; |
196 | unsigned m_minDeadCapacity { 0 }; |
197 | unsigned m_maxDeadCapacity; |
198 | Seconds m_deadDecodedDataDeletionInterval; |
199 | |
200 | unsigned m_liveSize { 0 }; // The number of bytes currently consumed by "live" resources in the cache. |
201 | unsigned m_deadSize { 0 }; // The number of bytes currently consumed by "dead" resources in the cache. |
202 | |
203 | // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold |
204 | // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are |
205 | // waiting to die when the clients referencing them go away. |
206 | Vector<std::unique_ptr<LRUList>, 32> m_allResources; |
207 | |
208 | // List just for live resources with decoded data. Access to this list is based off of painting the resource. |
209 | LRUList m_liveDecodedResources; |
210 | |
211 | // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being |
212 | // referenced by a Web page). |
213 | typedef HashMap<PAL::SessionID, std::unique_ptr<CachedResourceMap>> SessionCachedResourceMap; |
214 | SessionCachedResourceMap m_sessionResources; |
215 | |
216 | Timer m_pruneTimer; |
217 | }; |
218 | |
219 | } // namespace WebCore |
220 | |