diff options
Diffstat (limited to 'Source/WebCore/loader/cache/CachedResource.h')
-rw-r--r-- | Source/WebCore/loader/cache/CachedResource.h | 286 |
1 files changed, 154 insertions, 132 deletions
diff --git a/Source/WebCore/loader/cache/CachedResource.h b/Source/WebCore/loader/cache/CachedResource.h index 8de69cdbf..6f4e0e1b2 100644 --- a/Source/WebCore/loader/cache/CachedResource.h +++ b/Source/WebCore/loader/cache/CachedResource.h @@ -20,37 +20,37 @@ Boston, MA 02110-1301, USA. */ -#ifndef CachedResource_h -#define CachedResource_h +#pragma once #include "CachePolicy.h" +#include "CacheValidation.h" #include "FrameLoaderTypes.h" -#include "PurgePriority.h" #include "ResourceError.h" #include "ResourceLoadPriority.h" #include "ResourceLoaderOptions.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include "SessionID.h" #include "Timer.h" #include <time.h> #include <wtf/HashCountedSet.h> #include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> +#include <wtf/TypeCasts.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> namespace WebCore { -class MemoryCache; class CachedResourceClient; class CachedResourceHandleBase; class CachedResourceLoader; -class InspectorResource; -class PurgeableBuffer; -class ResourceBuffer; +class CachedResourceRequest; +class LoadTiming; +class MemoryCache; class SecurityOrigin; class SharedBuffer; class SubresourceLoader; +class TextResourceDecoder; // A resource that is held in the cache. Classes who want to use this object should derive // from CachedResourceClient, to get the function calls in case the requested data has arrived. @@ -58,8 +58,7 @@ class SubresourceLoader; class CachedResource { WTF_MAKE_NONCOPYABLE(CachedResource); WTF_MAKE_FAST_ALLOCATED; friend class MemoryCache; - friend class InspectorResource; - + public: enum Type { MainResource, @@ -67,10 +66,12 @@ public: CSSStyleSheet, Script, FontResource, - RawResource -#if ENABLE(SVG) - , SVGDocumentResource +#if ENABLE(SVG_FONTS) + SVGFontResource, #endif + MediaResource, + RawResource, + SVGDocumentResource #if ENABLE(XSLT) , XSLStyleSheet #endif @@ -91,16 +92,17 @@ public: DecodeError }; - CachedResource(const ResourceRequest&, Type); + CachedResource(CachedResourceRequest&&, Type, SessionID); virtual ~CachedResource(); - virtual void load(CachedResourceLoader*, const ResourceLoaderOptions&); + virtual void load(CachedResourceLoader&); virtual void setEncoding(const String&) { } virtual String encoding() const { return String(); } - virtual void addDataBuffer(ResourceBuffer*); + virtual const TextResourceDecoder* textResourceDecoder() const { return nullptr; } + virtual void addDataBuffer(SharedBuffer&); virtual void addData(const char* data, unsigned length); - virtual void finishLoading(ResourceBuffer*); + virtual void finishLoading(SharedBuffer*); virtual void error(CachedResource::Status); void setResourceError(const ResourceError& error) { m_error = error; } @@ -108,20 +110,20 @@ public: virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; } + const ResourceRequest& resourceRequest() const { return m_resourceRequest; } ResourceRequest& resourceRequest() { return m_resourceRequest; } const URL& url() const { return m_resourceRequest.url();} -#if ENABLE(CACHE_PARTITIONING) const String& cachePartition() const { return m_resourceRequest.cachePartition(); } -#endif - Type type() const { return static_cast<Type>(m_type); } - + SessionID sessionID() const { return m_sessionID; } + Type type() const { return m_type; } + ResourceLoadPriority loadPriority() const { return m_loadPriority; } - void setLoadPriority(ResourceLoadPriority); + void setLoadPriority(const std::optional<ResourceLoadPriority>&); - void addClient(CachedResourceClient*); - void removeClient(CachedResourceClient*); + WEBCORE_EXPORT void addClient(CachedResourceClient&); + WEBCORE_EXPORT void removeClient(CachedResourceClient&); bool hasClients() const { return !m_clients.isEmpty() || !m_clientsAwaitingCallback.isEmpty(); } - bool hasClient(CachedResourceClient* client) { return m_clients.contains(client) || m_clientsAwaitingCallback.contains(client); } + bool hasClient(CachedResourceClient& client) { return m_clients.contains(&client) || m_clientsAwaitingCallback.contains(&client); } bool deleteIfPossible(); enum PreloadResult { @@ -132,8 +134,8 @@ public: }; PreloadResult preloadResult() const { return static_cast<PreloadResult>(m_preloadResult); } - virtual void didAddClient(CachedResourceClient*); - virtual void didRemoveClient(CachedResourceClient*) { } + virtual void didAddClient(CachedResourceClient&); + virtual void didRemoveClient(CachedResourceClient&) { } virtual void allClientsRemoved() { } void destroyDecodedDataIfNeeded(); @@ -146,7 +148,7 @@ public: unsigned encodedSize() const { return m_encodedSize; } unsigned decodedSize() const { return m_decodedSize; } unsigned overheadSize() const; - + bool isLoaded() const { return !m_loading; } // FIXME. Method name is inaccurate. Loading might not have started yet. bool isLoading() const { return m_loading; } @@ -155,10 +157,15 @@ public: SubresourceLoader* loader() { return m_loader.get(); } - virtual bool isImage() const { return false; } + bool areAllClientsXMLHttpRequests() const; + + bool isImage() const { return type() == ImageResource; } + // FIXME: CachedRawResource could be a main resource, an audio/video resource, or a raw XHR/icon resource. + bool isMainOrMediaOrRawResource() const { return type() == MainResource || type() == MediaResource || type() == RawResource; } bool ignoreForRequestCount() const { - return type() == MainResource + return m_resourceRequest.ignoreForRequestCount() + || type() == MainResource #if ENABLE(LINK_PREFETCH) || type() == LinkPrefetch || type() == LinkSubresource @@ -169,205 +176,220 @@ public: unsigned accessCount() const { return m_accessCount; } void increaseAccessCount() { m_accessCount++; } - // Computes the status of an object after loading. + // Computes the status of an object after loading. // Updates the expire date on the cache entry file void finish(); - bool passesAccessControlCheck(SecurityOrigin*); - // Called by the cache if the object has been removed from the cache // while still being referenced. This means the object should delete itself // if the number of clients observing it ever drops to 0. // The resource can be brought back to cache after successful revalidation. void setInCache(bool inCache) { m_inCache = inCache; } bool inCache() const { return m_inCache; } - - bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } - + void clearLoader(); - ResourceBuffer* resourceBuffer() const { ASSERT(!m_purgeableData); return m_data.get(); } + SharedBuffer* resourceBuffer() const { return m_data.get(); } - virtual void willSendRequest(ResourceRequest&, const ResourceResponse&) { m_requestedFromNetworkingLayer = true; } + virtual void redirectReceived(ResourceRequest&, const ResourceResponse&); virtual void responseReceived(const ResourceResponse&); - void setResponse(const ResourceResponse& response) { m_response = response; } + virtual bool shouldCacheResponse(const ResourceResponse&) { return true; } + void setResponse(const ResourceResponse&); const ResourceResponse& response() const { return m_response; } + void setCrossOrigin(); + bool isCrossOrigin() const; + bool isCORSSameOrigin() const; + ResourceResponse::Tainting responseTainting() const { return m_responseTainting; } + + void loadFrom(const CachedResource&); + + SecurityOrigin* origin() const { return m_origin.get(); } + AtomicString initiatorName() const { return m_initiatorName; } + bool canDelete() const { return !hasClients() && !m_loader && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_proxyResource; } bool hasOneHandle() const { return m_handleCount == 1; } bool isExpired() const; - // List of acceptable MIME types separated by ",". - // A MIME type may contain a wildcard, e.g. "text/*". - String accept() const { return m_accept; } - void setAccept(const String& accept) { m_accept = accept; } - void cancelLoad(); bool wasCanceled() const { return m_error.isCancellation(); } bool errorOccurred() const { return m_status == LoadError || m_status == DecodeError; } - bool loadFailedOrCanceled() { return !m_error.isNull(); } + bool loadFailedOrCanceled() const { return !m_error.isNull(); } bool shouldSendResourceLoadCallbacks() const { return m_options.sendLoadCallbacks == SendCallbacks; } DataBufferingPolicy dataBufferingPolicy() const { return m_options.dataBufferingPolicy; } - + + bool allowsCaching() const { return m_options.cachingPolicy == CachingPolicy::AllowCaching; } + const FetchOptions& options() const { return m_options; } + virtual void destroyDecodedData() { } void setOwningCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) { m_owningCachedResourceLoader = cachedResourceLoader; } - + bool isPreloaded() const { return m_preloadCount; } void increasePreloadCount() { ++m_preloadCount; } void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } - - void registerHandle(CachedResourceHandleBase* h); - void unregisterHandle(CachedResourceHandleBase* h); - + bool isLinkPreload() { return m_isLinkPreload; } + void setLinkPreload() { m_isLinkPreload = true; } + + void registerHandle(CachedResourceHandleBase*); + WEBCORE_EXPORT void unregisterHandle(CachedResourceHandleBase*); + bool canUseCacheValidator() const; - virtual bool mustRevalidateDueToCacheHeaders(CachePolicy) const; + enum class RevalidationDecision { No, YesDueToCachePolicy, YesDueToNoStore, YesDueToNoCache, YesDueToExpired }; + virtual RevalidationDecision makeRevalidationDecision(CachePolicy) const; + bool redirectChainAllowsReuse(ReuseExpiredRedirectionOrNot) const; + bool hasRedirections() const { return m_redirectChainCacheStatus.status != RedirectChainCacheStatus::Status::NoRedirection; } + + bool varyHeaderValuesMatch(const ResourceRequest&); bool isCacheValidator() const { return m_resourceToRevalidate; } CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } - - bool isPurgeable() const; - bool wasPurged() const; - - // This is used by the archive machinery to get at a purged resource without - // triggering a load. We should make it protected again if we can find a - // better way to handle the archive case. - bool makePurgeable(bool purgeable); - + // HTTP revalidation support methods for CachedResourceLoader. void setResourceToRevalidate(CachedResource*); virtual void switchClientsToRevalidatedResource(); void clearResourceToRevalidate(); void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); - + bool validationInProgress() const { return m_proxyResource; } + bool validationCompleting() const { return m_proxyResource && m_proxyResource->m_switchingClientsToRevalidatedResource; } + virtual void didSendData(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { } + virtual void didRetrieveDerivedDataFromCache(const String& /* type */, SharedBuffer&) { } + void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; } double loadFinishTime() const { return m_loadFinishTime; } -#if ENABLE(DISK_IMAGE_CACHE) - bool isUsingDiskImageCache() const; - virtual bool canUseDiskImageCache() const { return false; } - virtual void useDiskImageCache() { ASSERT(canUseDiskImageCache()); } -#endif - - virtual bool canReuse(const ResourceRequest&) const { return true; } - -#if PLATFORM(MAC) - void tryReplaceEncodedData(PassRefPtr<SharedBuffer>); +#if USE(FOUNDATION) || USE(SOUP) + WEBCORE_EXPORT void tryReplaceEncodedData(SharedBuffer&); #endif #if USE(SOUP) - virtual char* getOrCreateReadBuffer(size_t /* requestedSize */, size_t& /* actualSize */) { return 0; } + virtual char* getOrCreateReadBuffer(size_t /* requestedSize */, size_t& /* actualSize */) { return nullptr; } #endif + unsigned long identifierForLoadWithoutResourceLoader() const { return m_identifierForLoadWithoutResourceLoader; } + static ResourceLoadPriority defaultPriorityForResourceType(Type); + protected: - virtual void checkNotify(); + // CachedResource constructor that may be used when the CachedResource can already be filled with response data. + CachedResource(const URL&, Type, SessionID); void setEncodedSize(unsigned); void setDecodedSize(unsigned); void didAccessDecodedData(double timeStamp); - bool isSafeToMakePurgeable() const; - - HashCountedSet<CachedResourceClient*> m_clients; + virtual void didReplaceSharedBufferContents() { } - class CachedResourceCallback { - public: - static PassOwnPtr<CachedResourceCallback> schedule(CachedResource* resource, CachedResourceClient* client) { return adoptPtr(new CachedResourceCallback(resource, client)); } - void cancel(); - private: - CachedResourceCallback(CachedResource*, CachedResourceClient*); - void timerFired(Timer<CachedResourceCallback>&); - - CachedResource* m_resource; - CachedResourceClient* m_client; - Timer<CachedResourceCallback> m_callbackTimer; - }; - HashMap<CachedResourceClient*, OwnPtr<CachedResourceCallback>> m_clientsAwaitingCallback; + virtual void setBodyDataFrom(const CachedResource&); + // FIXME: Make the rest of these data members private and use functions in derived classes instead. + HashCountedSet<CachedResourceClient*> m_clients; ResourceRequest m_resourceRequest; - String m_accept; RefPtr<SubresourceLoader> m_loader; ResourceLoaderOptions m_options; - ResourceLoadPriority m_loadPriority; - ResourceResponse m_response; - double m_responseTimestamp; - - RefPtr<ResourceBuffer> m_data; - OwnPtr<PurgeableBuffer> m_purgeableData; - DeferrableOneShotTimer<CachedResource> m_decodedDataDeletionTimer; + ResourceResponse::Tainting m_responseTainting { ResourceResponse::Tainting::Basic }; + RefPtr<SharedBuffer> m_data; + DeferrableOneShotTimer m_decodedDataDeletionTimer; private: - bool addClientToSet(CachedResourceClient*); + class Callback; + + bool addClientToSet(CachedResourceClient&); - void decodedDataDeletionTimerFired(DeferrableOneShotTimer<CachedResource>&); + void decodedDataDeletionTimerFired(); - virtual PurgePriority purgePriority() const { return PurgeDefault; } + virtual void checkNotify(); virtual bool mayTryReplaceEncodedData() const { return false; } - double currentAge() const; - double freshnessLifetime() const; + std::chrono::microseconds freshnessLifetime(const ResourceResponse&) const; - void addAdditionalRequestHeaders(CachedResourceLoader*); + void addAdditionalRequestHeaders(CachedResourceLoader&); void failBeforeStarting(); + HashMap<CachedResourceClient*, std::unique_ptr<Callback>> m_clientsAwaitingCallback; + SessionID m_sessionID; + ResourceLoadPriority m_loadPriority; + std::chrono::system_clock::time_point m_responseTimestamp; + String m_fragmentIdentifierForRequest; ResourceError m_error; + RefPtr<SecurityOrigin> m_origin; + AtomicString m_initiatorName; - double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache - double m_loadFinishTime; + double m_lastDecodedAccessTime { 0 }; // Used as a "thrash guard" in the cache + double m_loadFinishTime { 0 }; - unsigned m_encodedSize; - unsigned m_decodedSize; - unsigned m_accessCount; - unsigned m_handleCount; - unsigned m_preloadCount; + unsigned m_encodedSize { 0 }; + unsigned m_decodedSize { 0 }; + unsigned m_accessCount { 0 }; + unsigned m_handleCount { 0 }; + unsigned m_preloadCount { 0 }; - unsigned m_preloadResult : 2; // PreloadResult + PreloadResult m_preloadResult { PreloadNotReferenced }; - bool m_inLiveDecodedResourcesList : 1; - bool m_requestedFromNetworkingLayer : 1; + bool m_requestedFromNetworkingLayer { false }; - bool m_inCache : 1; - bool m_loading : 1; + bool m_inCache { false }; + bool m_loading { false }; + bool m_isLinkPreload { false }; - bool m_switchingClientsToRevalidatedResource : 1; + bool m_switchingClientsToRevalidatedResource { false }; - unsigned m_type : 4; // Type - unsigned m_status : 3; // Status + Type m_type; // Type + unsigned m_status { Pending }; // Status #ifndef NDEBUG - bool m_deleted; - unsigned m_lruIndex; + bool m_deleted { false }; + unsigned m_lruIndex { 0 }; #endif - CachedResource* m_nextInAllResourcesList; - CachedResource* m_prevInAllResourcesList; - - CachedResource* m_nextInLiveResourcesList; - CachedResource* m_prevInLiveResourcesList; + CachedResourceLoader* m_owningCachedResourceLoader { nullptr }; // only non-null for resources that are not in the cache - CachedResourceLoader* m_owningCachedResourceLoader; // only non-0 for resources that are not in the cache - // 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 // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this // resources becomes normal resource load. - CachedResource* m_resourceToRevalidate; + CachedResource* m_resourceToRevalidate { nullptr }; // If this field is non-null, the resource has a proxy for checking whether it is still up to date (see m_resourceToRevalidate). - CachedResource* m_proxyResource; + CachedResource* m_proxyResource { nullptr }; // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. HashSet<CachedResourceHandleBase*> m_handlesToRevalidate; -}; -} + RedirectChainCacheStatus m_redirectChainCacheStatus; + + Vector<std::pair<String, String>> m_varyingHeaderValues; + + unsigned long m_identifierForLoadWithoutResourceLoader { 0 }; +}; +class CachedResource::Callback { +#if !COMPILER(MSVC) + WTF_MAKE_FAST_ALLOCATED; #endif +public: + Callback(CachedResource&, CachedResourceClient&); + + void cancel(); + +private: + void timerFired(); + + CachedResource& m_resource; + CachedResourceClient& m_client; + Timer m_timer; +}; + +} // namespace WebCore + +#define SPECIALIZE_TYPE_TRAITS_CACHED_RESOURCE(ToClassName, CachedResourceType) \ +SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToClassName) \ + static bool isType(const WebCore::CachedResource& resource) { return resource.type() == WebCore::CachedResourceType; } \ +SPECIALIZE_TYPE_TRAITS_END() |