summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/cache/CachedResource.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/loader/cache/CachedResource.h')
-rw-r--r--Source/WebCore/loader/cache/CachedResource.h286
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()