1 /* 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 3 Copyright (C) 2001 Dirk Mueller <mueller@kde.org> 4 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) 5 Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public License 18 along with this library; see the file COPYING.LIB. If not, write to 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 Boston, MA 02110-1301, USA. 21 */ 22 23 #ifndef CachedResource_h 24 #define CachedResource_h 25 26 #include "CachePolicy.h" 27 #include "PlatformString.h" 28 #include "ResourceResponse.h" 29 #include "SharedBuffer.h" 30 #include <wtf/HashCountedSet.h> 31 #include <wtf/HashSet.h> 32 #include <wtf/OwnPtr.h> 33 #include <wtf/Vector.h> 34 #include <time.h> 35 36 namespace WebCore { 37 38 class Cache; 39 class CachedResourceClient; 40 class CachedResourceHandleBase; 41 class DocLoader; 42 class InspectorResource; 43 class Request; 44 class PurgeableBuffer; 45 46 // A resource that is held in the cache. Classes who want to use this object should derive 47 // from CachedResourceClient, to get the function calls in case the requested data has arrived. 48 // This class also does the actual communication with the loader to obtain the resource from the network. 49 class CachedResource { 50 friend class Cache; 51 friend class InspectorResource; 52 53 public: 54 enum Type { 55 ImageResource, 56 CSSStyleSheet, 57 Script, 58 FontResource 59 #if ENABLE(XSLT) 60 , XSLStyleSheet 61 #endif 62 #if ENABLE(XBL) 63 , XBL 64 #endif 65 }; 66 67 enum Status { 68 NotCached, // this URL is not cached 69 Unknown, // let cache decide what to do with it 70 New, // inserting new item 71 Pending, // only partially loaded 72 Cached // regular case 73 }; 74 75 CachedResource(const String& url, Type); 76 virtual ~CachedResource(); 77 load(DocLoader * docLoader)78 virtual void load(DocLoader* docLoader) { load(docLoader, false, false, true); } 79 void load(DocLoader*, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks); 80 setEncoding(const String &)81 virtual void setEncoding(const String&) { } encoding()82 virtual String encoding() const { return String(); } 83 virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived) = 0; 84 virtual void error() = 0; httpStatusCodeError()85 virtual void httpStatusCodeError() { error(); } // Images keep loading in spite of HTTP errors (for legacy compat with <img>, etc.). 86 url()87 const String &url() const { return m_url; } type()88 Type type() const { return m_type; } 89 90 void addClient(CachedResourceClient*); 91 void removeClient(CachedResourceClient*); hasClients()92 bool hasClients() const { return !m_clients.isEmpty(); } 93 void deleteIfPossible(); 94 95 enum PreloadResult { 96 PreloadNotReferenced, 97 PreloadReferenced, 98 PreloadReferencedWhileLoading, 99 PreloadReferencedWhileComplete 100 }; preloadResult()101 PreloadResult preloadResult() const { return m_preloadResult; } setRequestedFromNetworkingLayer()102 void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; } 103 104 virtual void didAddClient(CachedResourceClient*) = 0; allClientsRemoved()105 virtual void allClientsRemoved() { } 106 count()107 unsigned count() const { return m_clients.size(); } 108 status()109 Status status() const { return m_status; } 110 size()111 unsigned size() const { return encodedSize() + decodedSize() + overheadSize(); } encodedSize()112 unsigned encodedSize() const { return m_encodedSize; } decodedSize()113 unsigned decodedSize() const { return m_decodedSize; } 114 unsigned overheadSize() const; 115 isLoaded()116 bool isLoaded() const { return !m_loading; } setLoading(bool b)117 void setLoading(bool b) { m_loading = b; } 118 isImage()119 virtual bool isImage() const { return false; } 120 accessCount()121 unsigned accessCount() const { return m_accessCount; } increaseAccessCount()122 void increaseAccessCount() { m_accessCount++; } 123 124 // Computes the status of an object after loading. 125 // Updates the expire date on the cache entry file 126 void finish(); 127 128 // Called by the cache if the object has been removed from the cache 129 // while still being referenced. This means the object should delete itself 130 // if the number of clients observing it ever drops to 0. 131 // The resource can be brought back to cache after successful revalidation. setInCache(bool b)132 void setInCache(bool b) { m_inCache = b; if (b) m_isBeingRevalidated = false; } inCache()133 bool inCache() const { return m_inCache; } 134 setInLiveDecodedResourcesList(bool b)135 void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } inLiveDecodedResourcesList()136 bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } 137 138 void setRequest(Request*); 139 data()140 SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); } 141 142 void setResponse(const ResourceResponse&); response()143 const ResourceResponse& response() const { return m_response; } 144 canDelete()145 bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_isBeingRevalidated; } 146 147 bool isExpired() const; 148 schedule()149 virtual bool schedule() const { return false; } 150 151 // List of acceptable MIME types seperated by ",". 152 // A MIME type may contain a wildcard, e.g. "text/*". accept()153 String accept() const { return m_accept; } setAccept(const String & accept)154 void setAccept(const String& accept) { m_accept = accept; } 155 errorOccurred()156 bool errorOccurred() const { return m_errorOccurred; } sendResourceLoadCallbacks()157 bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } 158 destroyDecodedData()159 virtual void destroyDecodedData() { } 160 setDocLoader(DocLoader * docLoader)161 void setDocLoader(DocLoader* docLoader) { m_docLoader = docLoader; } 162 isPreloaded()163 bool isPreloaded() const { return m_preloadCount; } increasePreloadCount()164 void increasePreloadCount() { ++m_preloadCount; } decreasePreloadCount()165 void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } 166 registerHandle(CachedResourceHandleBase * h)167 void registerHandle(CachedResourceHandleBase* h) { ++m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.add(h); } unregisterHandle(CachedResourceHandleBase * h)168 void unregisterHandle(CachedResourceHandleBase* h) { ASSERT(m_handleCount > 0); --m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.remove(h); if (!m_handleCount) deleteIfPossible(); } 169 170 bool canUseCacheValidator() const; 171 bool mustRevalidate(CachePolicy) const; isCacheValidator()172 bool isCacheValidator() const { return m_resourceToRevalidate; } resourceToRevalidate()173 CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } 174 175 bool isPurgeable() const; 176 bool wasPurged() const; 177 178 // This is used by the archive machinery to get at a purged resource without 179 // triggering a load. We should make it protected again if we can find a 180 // better way to handle the archive case. 181 bool makePurgeable(bool purgeable); 182 183 protected: 184 void setEncodedSize(unsigned); 185 void setDecodedSize(unsigned); 186 void didAccessDecodedData(double timeStamp); 187 188 bool isSafeToMakePurgeable() const; 189 190 HashCountedSet<CachedResourceClient*> m_clients; 191 192 String m_url; 193 String m_accept; 194 Request* m_request; 195 196 ResourceResponse m_response; 197 double m_responseTimestamp; 198 199 RefPtr<SharedBuffer> m_data; 200 OwnPtr<PurgeableBuffer> m_purgeableData; 201 202 Type m_type; 203 Status m_status; 204 205 bool m_errorOccurred; 206 207 private: 208 void addClientToSet(CachedResourceClient*); 209 210 // These are called by the friendly Cache only 211 void setResourceToRevalidate(CachedResource*); 212 void switchClientsToRevalidatedResource(); 213 void clearResourceToRevalidate(); 214 void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); 215 216 double currentAge() const; 217 double freshnessLifetime() const; 218 219 unsigned m_encodedSize; 220 unsigned m_decodedSize; 221 unsigned m_accessCount; 222 unsigned m_inLiveDecodedResourcesList; 223 double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache 224 225 bool m_sendResourceLoadCallbacks; 226 227 unsigned m_preloadCount; 228 PreloadResult m_preloadResult; 229 bool m_requestedFromNetworkingLayer; 230 231 protected: 232 bool m_inCache; 233 bool m_loading; 234 #ifndef NDEBUG 235 bool m_deleted; 236 unsigned m_lruIndex; 237 #endif 238 239 private: 240 CachedResource* m_nextInAllResourcesList; 241 CachedResource* m_prevInAllResourcesList; 242 243 CachedResource* m_nextInLiveResourcesList; 244 CachedResource* m_prevInLiveResourcesList; 245 246 DocLoader* m_docLoader; // only non-0 for resources that are not in the cache 247 248 unsigned m_handleCount; 249 // If this field is non-null we are using the resource as a proxy for checking whether an existing resource is still up to date 250 // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved 251 // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this 252 // resources becomes normal resource load. 253 CachedResource* m_resourceToRevalidate; 254 bool m_isBeingRevalidated; 255 // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. 256 HashSet<CachedResourceHandleBase*> m_handlesToRevalidate; 257 }; 258 259 } 260 261 #endif 262