Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / fetch / Resource.h
blob28944d85bfa91e82b4444d540888a0a3f6c04317
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, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
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.
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.
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.
23 #ifndef Resource_h
24 #define Resource_h
26 #include "core/CoreExport.h"
27 #include "core/fetch/CachedMetadataHandler.h"
28 #include "core/fetch/ResourceLoaderOptions.h"
29 #include "platform/Timer.h"
30 #include "platform/network/ResourceError.h"
31 #include "platform/network/ResourceLoadPriority.h"
32 #include "platform/network/ResourceRequest.h"
33 #include "platform/network/ResourceResponse.h"
34 #include "public/platform/WebDataConsumerHandle.h"
35 #include "wtf/Allocator.h"
36 #include "wtf/HashCountedSet.h"
37 #include "wtf/HashSet.h"
38 #include "wtf/OwnPtr.h"
39 #include "wtf/text/WTFString.h"
41 // FIXME(crbug.com/352043): This is temporarily enabled even on RELEASE to diagnose a wild crash.
42 #define ENABLE_RESOURCE_IS_DELETED_CHECK
44 namespace blink {
46 struct FetchInitiatorInfo;
47 class CachedMetadata;
48 class ResourceClient;
49 class ResourcePtrBase;
50 class ResourceFetcher;
51 class ResourceTimingInfo;
52 class InspectorResource;
53 class ResourceLoader;
54 class SecurityOrigin;
55 class SharedBuffer;
57 // A resource that is held in the cache. Classes who want to use this object should derive
58 // from ResourceClient, to get the function calls in case the requested data has arrived.
59 // This class also does the actual communication with the loader to obtain the resource from the network.
60 class CORE_EXPORT Resource : public NoBaseWillBeGarbageCollectedFinalized<Resource> {
61 WTF_MAKE_NONCOPYABLE(Resource); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(Resource);
62 friend class InspectorResource;
64 public:
65 enum Type {
66 MainResource,
67 Image,
68 CSSStyleSheet,
69 Script,
70 Font,
71 Raw,
72 SVGDocument,
73 XSLStyleSheet,
74 LinkPrefetch,
75 LinkSubresource,
76 LinkPreload,
77 TextTrack,
78 ImportResource,
79 Media // Audio or video file requested by a HTML5 media element
82 enum Status {
83 Unknown, // let cache decide what to do with it
84 Pending, // only partially loaded
85 Cached, // regular case
86 LoadError,
87 DecodeError
90 // Exposed for testing.
91 Resource(const ResourceRequest&, Type);
92 #if ENABLE(OILPAN)
93 virtual ~Resource();
94 #else
95 protected:
96 // Only deleteIfPossible should delete this.
97 virtual ~Resource();
98 public:
99 #endif
100 virtual void dispose();
101 DECLARE_VIRTUAL_TRACE();
103 virtual void load(ResourceFetcher*, const ResourceLoaderOptions&);
105 virtual void setEncoding(const String&) { }
106 virtual String encoding() const { return String(); }
107 virtual void appendData(const char*, unsigned);
108 virtual void error(Resource::Status);
109 virtual void setCORSFailed() { }
111 void setNeedsSynchronousCacheHit(bool needsSynchronousCacheHit) { m_needsSynchronousCacheHit = needsSynchronousCacheHit; }
113 void setResourceError(const ResourceError& error) { m_error = error; }
114 const ResourceError& resourceError() const { return m_error; }
116 void setIdentifier(unsigned long identifier) { m_identifier = identifier; }
117 unsigned long identifier() const { return m_identifier; }
119 virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; }
121 ResourceRequest& mutableResourceRequest() { return m_resourceRequest; }
122 const ResourceRequest& resourceRequest() const { return m_resourceRequest; }
123 const ResourceRequest& lastResourceRequest() const;
125 const KURL& url() const { return m_resourceRequest.url();}
126 Type type() const { return static_cast<Type>(m_type); }
127 const ResourceLoaderOptions& options() const { return m_options; }
128 void setOptions(const ResourceLoaderOptions& options) { m_options = options; }
130 void didChangePriority(ResourceLoadPriority, int intraPriorityValue);
132 void addClient(ResourceClient*);
133 void removeClient(ResourceClient*);
134 bool hasClients() const { return !m_clients.isEmpty() || !m_clientsAwaitingCallback.isEmpty(); }
135 bool deleteIfPossible();
137 enum PreloadResult {
138 PreloadNotReferenced,
139 PreloadReferenced,
140 PreloadReferencedWhileLoading,
141 PreloadReferencedWhileComplete
143 PreloadResult preloadResult() const { return static_cast<PreloadResult>(m_preloadResult); }
145 virtual void didAddClient(ResourceClient*);
146 virtual void didRemoveClient(ResourceClient*) { }
147 virtual void allClientsRemoved();
149 unsigned count() const { return m_clients.size(); }
151 Status status() const { return static_cast<Status>(m_status); }
152 void setStatus(Status status) { m_status = status; }
154 size_t size() const { return encodedSize() + decodedSize() + overheadSize(); }
155 size_t encodedSize() const { return m_encodedSize; }
156 size_t decodedSize() const { return m_decodedSize; }
157 size_t overheadSize() const;
159 bool isLoaded() const { return !m_loading; } // FIXME. Method name is inaccurate. Loading might not have started yet.
161 bool isLoading() const { return m_loading; }
162 void setLoading(bool b) { m_loading = b; }
163 virtual bool stillNeedsLoad() const { return false; }
165 ResourceLoader* loader() const { return m_loader.get(); }
167 virtual bool isImage() const { return false; }
168 bool shouldBlockLoadEvent() const
170 return type() != LinkPrefetch
171 && type() != LinkSubresource
172 && type() != Media
173 && type() != Raw
174 && type() != TextTrack;
177 // Computes the status of an object after loading.
178 // Updates the expire date on the cache entry file
179 void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; }
180 void finish();
182 // FIXME: Remove the stringless variant once all the callsites' error messages are updated.
183 bool passesAccessControlCheck(SecurityOrigin*) const;
184 bool passesAccessControlCheck(SecurityOrigin*, String& errorDescription) const;
186 bool isEligibleForIntegrityCheck(SecurityOrigin*) const;
188 void clearLoader();
190 SharedBuffer* resourceBuffer() const { return m_data.get(); }
191 void setResourceBuffer(PassRefPtr<SharedBuffer>);
193 virtual void willFollowRedirect(ResourceRequest&, const ResourceResponse&);
195 virtual void updateRequest(const ResourceRequest&) { }
196 virtual void responseReceived(const ResourceResponse&, PassOwnPtr<WebDataConsumerHandle>);
197 void setResponse(const ResourceResponse& response) { m_response = response; }
198 const ResourceResponse& response() const { return m_response; }
200 virtual void reportResourceTimingToClients(const ResourceTimingInfo&) { }
202 // Sets the serialized metadata retrieved from the platform's cache.
203 virtual void setSerializedCachedMetadata(const char*, size_t);
205 // This may return nullptr when the resource isn't cacheable.
206 CachedMetadataHandler* cacheHandler();
208 bool hasOneHandle() const;
209 bool canDelete() const;
211 // List of acceptable MIME types separated by ",".
212 // A MIME type may contain a wildcard, e.g. "text/*".
213 AtomicString accept() const { return m_accept; }
214 void setAccept(const AtomicString& accept) { m_accept = accept; }
216 bool wasCanceled() const { return m_error.isCancellation(); }
217 bool errorOccurred() const { return m_status == LoadError || m_status == DecodeError; }
218 bool loadFailedOrCanceled() { return !m_error.isNull(); }
220 DataBufferingPolicy dataBufferingPolicy() const { return m_options.dataBufferingPolicy; }
221 void setDataBufferingPolicy(DataBufferingPolicy);
223 bool isUnusedPreload() const { return isPreloaded() && preloadResult() == PreloadNotReferenced; }
224 bool isPreloaded() const { return m_preloadCount; }
225 void increasePreloadCount() { ++m_preloadCount; }
226 void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; }
228 void registerHandle(ResourcePtrBase* h);
229 void unregisterHandle(ResourcePtrBase* h);
231 bool canReuseRedirectChain();
232 bool mustRevalidateDueToCacheHeaders();
233 bool canUseCacheValidator();
234 bool isCacheValidator() const { return m_resourceToRevalidate; }
235 Resource* resourceToRevalidate() const { return m_resourceToRevalidate; }
236 void setResourceToRevalidate(Resource*);
237 bool hasCacheControlNoStoreHeader();
238 bool hasVaryHeader() const;
240 double currentAge() const;
241 double freshnessLifetime();
242 double stalenessLifetime();
244 bool isPurgeable() const;
245 bool wasPurged() const;
246 bool lock();
248 void setCacheIdentifier(const String& cacheIdentifier) { m_cacheIdentifier = cacheIdentifier; }
249 String cacheIdentifier() const { return m_cacheIdentifier; }
251 virtual void didSendData(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { }
252 virtual void didDownloadData(int) { }
254 double loadFinishTime() const { return m_loadFinishTime; }
256 virtual bool canReuse(const ResourceRequest&) const { return true; }
258 // Used by the MemoryCache to reduce the memory consumption of the entry.
259 void prune();
261 static const char* resourceTypeToString(Type, const FetchInitiatorInfo&);
263 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
264 void assertAlive() const { RELEASE_ASSERT(!m_deleted); }
265 #else
266 void assertAlive() const { }
267 #endif
269 protected:
270 virtual void checkNotify();
271 virtual void finishOnePart();
273 // Normal resource pointers will silently switch what Resource* they reference when we
274 // successfully revalidated the resource. We need a way to guarantee that the Resource
275 // that received the 304 response survives long enough to switch everything over to the
276 // revalidatedresource. The normal mechanisms for keeping a Resource alive externally
277 // (ResourcePtrs and ResourceClients registering themselves) don't work in this case, so
278 // have a separate internal protector).
279 class InternalResourcePtr {
280 public:
281 explicit InternalResourcePtr(Resource* resource)
282 : m_resource(resource)
284 m_resource->incrementProtectorCount();
287 ~InternalResourcePtr()
289 m_resource->decrementProtectorCount();
290 m_resource->deleteIfPossible();
292 private:
293 Resource* m_resource;
296 void incrementProtectorCount() { m_protectorCount++; }
297 void decrementProtectorCount() { m_protectorCount--; }
299 void setEncodedSize(size_t);
300 void setDecodedSize(size_t);
301 void didAccessDecodedData();
303 void clearResourceToRevalidate();
304 void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse);
306 void finishPendingClients();
308 HashCountedSet<ResourceClient*> m_clients;
309 HashCountedSet<ResourceClient*> m_clientsAwaitingCallback;
311 class ResourceCallback : public NoBaseWillBeGarbageCollectedFinalized<ResourceCallback> {
312 public:
313 static ResourceCallback* callbackHandler();
314 DECLARE_TRACE();
315 void schedule(Resource*);
316 void cancel(Resource*);
317 bool isScheduled(Resource*) const;
318 private:
319 ResourceCallback();
320 void timerFired(Timer<ResourceCallback>*);
321 Timer<ResourceCallback> m_callbackTimer;
322 WillBeHeapHashSet<RawPtrWillBeMember<Resource>> m_resourcesWithPendingClients;
325 bool hasClient(ResourceClient* client) { return m_clients.contains(client) || m_clientsAwaitingCallback.contains(client); }
327 struct RedirectPair {
328 ALLOW_ONLY_INLINE_ALLOCATION();
329 public:
330 explicit RedirectPair(const ResourceRequest& request, const ResourceResponse& redirectResponse)
331 : m_request(request)
332 , m_redirectResponse(redirectResponse)
336 ResourceRequest m_request;
337 ResourceResponse m_redirectResponse;
339 const Vector<RedirectPair>& redirectChain() const { return m_redirectChain; }
341 virtual bool isSafeToUnlock() const { return false; }
342 virtual void destroyDecodedDataIfPossible() { }
344 ResourceRequest m_resourceRequest;
345 AtomicString m_accept;
346 PersistentWillBeMember<ResourceLoader> m_loader;
347 ResourceLoaderOptions m_options;
349 ResourceResponse m_response;
350 double m_responseTimestamp;
352 RefPtr<SharedBuffer> m_data;
353 Timer<Resource> m_cancelTimer;
355 private:
356 class CacheHandler;
357 bool addClientToSet(ResourceClient*);
358 void cancelTimerFired(Timer<Resource>*);
360 void switchClientsToRevalidatedResource();
361 void revalidationSucceeded(const ResourceResponse&);
362 void revalidationFailed();
364 bool unlock();
366 bool hasRightHandleCountApartFromCache(unsigned targetCount) const;
368 void setCachedMetadata(unsigned dataTypeID, const char*, size_t, CachedMetadataHandler::CacheType);
369 void clearCachedMetadata(CachedMetadataHandler::CacheType);
370 CachedMetadata* cachedMetadata(unsigned dataTypeID) const;
372 String m_fragmentIdentifierForRequest;
374 RefPtr<CachedMetadata> m_cachedMetadata;
375 OwnPtrWillBeMember<CacheHandler> m_cacheHandler;
377 ResourceError m_error;
379 double m_loadFinishTime;
381 unsigned long m_identifier;
383 size_t m_encodedSize;
384 size_t m_decodedSize;
385 unsigned m_handleCount;
386 unsigned m_preloadCount;
387 unsigned m_protectorCount;
389 String m_cacheIdentifier;
391 unsigned m_preloadResult : 2; // PreloadResult
392 unsigned m_requestedFromNetworkingLayer : 1;
394 unsigned m_loading : 1;
396 unsigned m_switchingClientsToRevalidatedResource : 1;
398 unsigned m_type : 4; // Type
399 unsigned m_status : 3; // Status
401 unsigned m_wasPurged : 1;
403 unsigned m_needsSynchronousCacheHit : 1;
405 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
406 bool m_deleted;
407 #endif
409 // 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
410 // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved
411 // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this
412 // resources becomes normal resource load.
413 RawPtrWillBeMember<Resource> m_resourceToRevalidate;
415 // If this field is non-null, the resource has a proxy for checking whether it is still up to date (see m_resourceToRevalidate).
416 RawPtrWillBeMember<Resource> m_proxyResource;
418 // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response.
419 HashSet<ResourcePtrBase*> m_handlesToRevalidate;
421 // Ordered list of all redirects followed while fetching this resource.
422 Vector<RedirectPair> m_redirectChain;
425 class ResourceFactory {
426 STACK_ALLOCATED();
427 public:
428 virtual Resource* create(const ResourceRequest&, const String&) const = 0;
429 Resource::Type type() const { return m_type; }
431 protected:
432 ResourceFactory(Resource::Type type) : m_type(type) { }
434 Resource::Type m_type;
437 #if !LOG_DISABLED
438 // Intended to be used in LOG statements.
439 const char* ResourceTypeName(Resource::Type);
440 #endif
442 #define DEFINE_RESOURCE_TYPE_CASTS(typeName) \
443 DEFINE_TYPE_CASTS(typeName##Resource, Resource, resource, resource->type() == Resource::typeName, resource.type() == Resource::typeName); \
444 inline typeName##Resource* to##typeName##Resource(const ResourcePtr<Resource>& ptr) { return to##typeName##Resource(ptr.get()); }
448 #endif