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; 85 url()86 const String &url() const { return m_url; } type()87 Type type() const { return m_type; } 88 89 virtual void addClient(CachedResourceClient*); 90 void removeClient(CachedResourceClient*); hasClients()91 bool hasClients() const { return !m_clients.isEmpty(); } 92 void deleteIfPossible(); 93 94 enum PreloadResult { 95 PreloadNotReferenced, 96 PreloadReferenced, 97 PreloadReferencedWhileLoading, 98 PreloadReferencedWhileComplete 99 }; preloadResult()100 PreloadResult preloadResult() const { return m_preloadResult; } setRequestedFromNetworkingLayer()101 void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; } 102 allClientsRemoved()103 virtual void allClientsRemoved() { } 104 count()105 unsigned count() const { return m_clients.size(); } 106 status()107 Status status() const { return m_status; } 108 size()109 unsigned size() const { return encodedSize() + decodedSize() + overheadSize(); } encodedSize()110 unsigned encodedSize() const { return m_encodedSize; } decodedSize()111 unsigned decodedSize() const { return m_decodedSize; } 112 unsigned overheadSize() const; 113 isLoaded()114 bool isLoaded() const { return !m_loading; } setLoading(bool b)115 void setLoading(bool b) { m_loading = b; } 116 isImage()117 virtual bool isImage() const { return false; } 118 accessCount()119 unsigned accessCount() const { return m_accessCount; } increaseAccessCount()120 void increaseAccessCount() { m_accessCount++; } 121 122 // Computes the status of an object after loading. 123 // Updates the expire date on the cache entry file 124 void finish(); 125 126 // Called by the cache if the object has been removed from the cache 127 // while still being referenced. This means the object should delete itself 128 // if the number of clients observing it ever drops to 0. setInCache(bool b)129 void setInCache(bool b) { m_inCache = b; } inCache()130 bool inCache() const { return m_inCache; } 131 setInLiveDecodedResourcesList(bool b)132 void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } inLiveDecodedResourcesList()133 bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } 134 135 void setRequest(Request*); 136 data()137 SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); } 138 139 void setResponse(const ResourceResponse&); response()140 const ResourceResponse& response() const { return m_response; } 141 canDelete()142 bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_isBeingRevalidated; } 143 144 bool isExpired() const; 145 schedule()146 virtual bool schedule() const { return false; } 147 148 // List of acceptable MIME types seperated by ",". 149 // A MIME type may contain a wildcard, e.g. "text/*". accept()150 String accept() const { return m_accept; } setAccept(const String & accept)151 void setAccept(const String& accept) { m_accept = accept; } 152 errorOccurred()153 bool errorOccurred() const { return m_errorOccurred; } sendResourceLoadCallbacks()154 bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } 155 destroyDecodedData()156 virtual void destroyDecodedData() { } 157 setDocLoader(DocLoader * docLoader)158 void setDocLoader(DocLoader* docLoader) { m_docLoader = docLoader; } 159 isPreloaded()160 bool isPreloaded() const { return m_preloadCount; } increasePreloadCount()161 void increasePreloadCount() { ++m_preloadCount; } decreasePreloadCount()162 void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } 163 registerHandle(CachedResourceHandleBase * h)164 void registerHandle(CachedResourceHandleBase* h) { ++m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.add(h); } unregisterHandle(CachedResourceHandleBase * h)165 void unregisterHandle(CachedResourceHandleBase* h) { --m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.remove(h); if (!m_handleCount) deleteIfPossible(); } 166 167 bool canUseCacheValidator() const; 168 bool mustRevalidate(CachePolicy) const; isCacheValidator()169 bool isCacheValidator() const { return m_resourceToRevalidate; } resourceToRevalidate()170 CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } 171 172 bool isPurgeable() const; 173 bool wasPurged() const; 174 175 protected: 176 void setEncodedSize(unsigned); 177 void setDecodedSize(unsigned); 178 void didAccessDecodedData(double timeStamp); 179 180 bool makePurgeable(bool purgeable); 181 bool isSafeToMakePurgeable() const; 182 183 HashCountedSet<CachedResourceClient*> m_clients; 184 185 String m_url; 186 String m_accept; 187 Request* m_request; 188 189 ResourceResponse m_response; 190 RefPtr<SharedBuffer> m_data; 191 OwnPtr<PurgeableBuffer> m_purgeableData; 192 193 Type m_type; 194 Status m_status; 195 196 bool m_errorOccurred; 197 198 private: 199 // These are called by the friendly Cache only 200 void setResourceToRevalidate(CachedResource*); 201 void switchClientsToRevalidatedResource(); 202 void clearResourceToRevalidate(); setExpirationDate(time_t expirationDate)203 void setExpirationDate(time_t expirationDate) { m_expirationDate = expirationDate; } 204 205 unsigned m_encodedSize; 206 unsigned m_decodedSize; 207 unsigned m_accessCount; 208 unsigned m_inLiveDecodedResourcesList; 209 double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache 210 211 bool m_sendResourceLoadCallbacks; 212 213 unsigned m_preloadCount; 214 PreloadResult m_preloadResult; 215 bool m_requestedFromNetworkingLayer; 216 217 protected: 218 bool m_inCache; 219 bool m_loading; 220 bool m_expireDateChanged; 221 #ifndef NDEBUG 222 bool m_deleted; 223 unsigned m_lruIndex; 224 #endif 225 226 private: 227 CachedResource* m_nextInAllResourcesList; 228 CachedResource* m_prevInAllResourcesList; 229 230 CachedResource* m_nextInLiveResourcesList; 231 CachedResource* m_prevInLiveResourcesList; 232 233 DocLoader* m_docLoader; // only non-0 for resources that are not in the cache 234 235 unsigned m_handleCount; 236 // 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 237 // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved 238 // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this 239 // resources becomes normal resource load. 240 CachedResource* m_resourceToRevalidate; 241 bool m_isBeingRevalidated; 242 // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. 243 HashSet<CachedResourceHandleBase*> m_handlesToRevalidate; 244 245 time_t m_expirationDate; 246 }; 247 248 } 249 250 #endif 251