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#ifndef Cache_h
26#define Cache_h
27
28#include "NativeImagePtr.h"
29#include "SecurityOriginHash.h"
30#include "SessionID.h"
31#include "Timer.h"
32#include <wtf/Forward.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
41namespace WebCore {
42
43class CachedResource;
44class URL;
45class ResourceRequest;
46class ResourceResponse;
47class ScriptExecutionContext;
48class 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
63class MemoryCache {
64 WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
65 friend NeverDestroyed<MemoryCache>;
66 friend class Internals;
67public:
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&, SessionID);
96
97 bool add(CachedResource&);
98 void remove(CachedResource&);
99
100 static URL removeFragmentIdentifierIfNeeded(const URL& originalURL);
101
102 void revalidationSucceeded(CachedResource& revalidatingResource, const ResourceResponse&);
103 void revalidationFailed(CachedResource& revalidatingResource);
104
105 // Sets the cache's memory capacities, in bytes. These will hold only approximately,
106 // since the decoded cost of resources like scripts and stylesheets is not known.
107 // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure.
108 // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure.
109 // - totalBytes: The maximum number of bytes that the cache should consume overall.
110 WEBCORE_EXPORT void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes);
111
112 // Turn the cache on and off. Disabling the cache will remove all resources from the cache. They may
113 // still live on if they are referenced by some Web page though.
114 WEBCORE_EXPORT void setDisabled(bool);
115 bool disabled() const { return m_disabled; }
116
117 WEBCORE_EXPORT void evictResources();
118 WEBCORE_EXPORT void evictResources(SessionID);
119
120 void prune();
121 void pruneSoon();
122 unsigned size() const { return m_liveSize + m_deadSize; }
123
124 void setDeadDecodedDataDeletionInterval(std::chrono::milliseconds interval) { m_deadDecodedDataDeletionInterval = interval; }
125 std::chrono::milliseconds deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; }
126
127 // Calls to put the cached resource into and out of LRU lists.
128 void insertInLRUList(CachedResource&);
129 void removeFromLRUList(CachedResource&);
130
131 // Called to adjust the cache totals when a resource changes size.
132 void adjustSize(bool live, int delta);
133
134 // Track decoded resources that are in the cache and referenced by a Web page.
135 void insertInLiveDecodedResourcesList(CachedResource&);
136 void removeFromLiveDecodedResourcesList(CachedResource&);
137
138 void addToLiveResourcesSize(CachedResource&);
139 void removeFromLiveResourcesSize(CachedResource&);
140
141 static void removeRequestFromSessionCaches(ScriptExecutionContext&, const ResourceRequest&);
142
143 // Function to collect cache statistics for the caches window in the Safari Debug menu.
144 WEBCORE_EXPORT Statistics getStatistics();
145
146 void resourceAccessed(CachedResource&);
147 bool inLiveDecodedResourcesList(CachedResource& resource) const { return m_liveDecodedResources.contains(&resource); }
148
149 typedef HashSet<RefPtr<SecurityOrigin>> SecurityOriginSet;
150 WEBCORE_EXPORT void removeResourcesWithOrigin(SecurityOrigin&);
151 WEBCORE_EXPORT void removeResourcesWithOrigins(SessionID, const HashSet<RefPtr<SecurityOrigin>>&);
152 WEBCORE_EXPORT void getOriginsWithCache(SecurityOriginSet& origins);
153 WEBCORE_EXPORT HashSet<RefPtr<SecurityOrigin>> originsWithCache(SessionID) const;
154
155#if USE(CG)
156 // FIXME: Remove the USE(CG) once we either make NativeImagePtr a smart pointer on all platforms or
157 // remove the usage of CFRetain() in MemoryCache::addImageToCache() so as to make the code platform-independent.
158 WEBCORE_EXPORT bool addImageToCache(NativeImagePtr, const URL&, const String& domainForCachePartition);
159 WEBCORE_EXPORT void removeImageFromCache(const URL&, const String& domainForCachePartition);
160#endif
161
162 // pruneDead*() - Flush decoded and encoded data from resources not referenced by Web pages.
163 // pruneLive*() - Flush decoded data from resources still referenced by Web pages.
164 WEBCORE_EXPORT void pruneDeadResources(); // Automatically decide how much to prune.
165 WEBCORE_EXPORT void pruneLiveResources(bool shouldDestroyDecodedDataForAllLiveResources = false);
166
167 WEBCORE_EXPORT void pruneDeadResourcesToSize(unsigned targetSize);
168 WEBCORE_EXPORT void pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestroyDecodedDataForAllLiveResources = false);
169
170private:
171#if ENABLE(CACHE_PARTITIONING)
172 typedef HashMap<std::pair<URL, String /* partitionName */>, CachedResource*> CachedResourceMap;
173#else
174 typedef HashMap<URL, CachedResource*> CachedResourceMap;
175#endif
176 typedef ListHashSet<CachedResource*> LRUList;
177
178 MemoryCache();
179 ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
180
181 LRUList& lruListFor(CachedResource&);
182#ifndef NDEBUG
183 void dumpStats();
184 void dumpLRULists(bool includeLive) const;
185#endif
186
187 unsigned liveCapacity() const;
188 unsigned deadCapacity() const;
189 bool needsPruning() const;
190
191 CachedResource* resourceForRequestImpl(const ResourceRequest&, CachedResourceMap&);
192
193 CachedResourceMap& ensureSessionResourceMap(SessionID);
194 CachedResourceMap* sessionResourceMap(SessionID) const;
195
196 bool m_disabled; // Whether or not the cache is enabled.
197 bool m_inPruneResources;
198
199 unsigned m_capacity;
200 unsigned m_minDeadCapacity;
201 unsigned m_maxDeadCapacity;
202 std::chrono::milliseconds m_deadDecodedDataDeletionInterval;
203
204 unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache.
205 unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache.
206
207 // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold
208 // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
209 // waiting to die when the clients referencing them go away.
210 Vector<std::unique_ptr<LRUList>, 32> m_allResources;
211
212 // List just for live resources with decoded data. Access to this list is based off of painting the resource.
213 LRUList m_liveDecodedResources;
214
215 // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
216 // referenced by a Web page).
217 typedef HashMap<SessionID, std::unique_ptr<CachedResourceMap>> SessionCachedResourceMap;
218 SessionCachedResourceMap m_sessionResources;
219
220 Timer m_pruneTimer;
221};
222
223}
224
225#endif
226