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
41namespace WebCore {
42
43class CachedResource;
44class CookieJar;
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&, 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
171private:
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