/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
    Copyright (C) 2004-2011, 2014 Apple Inc. All rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "config.h"
#include "CachedResource.h"

#include "CachedResourceClient.h"
#include "CachedResourceClientWalker.h"
#include "CachedResourceHandle.h"
#include "CachedResourceLoader.h"
#include "CrossOriginAccessControl.h"
#include "DiagnosticLoggingClient.h"
#include "DiagnosticLoggingKeys.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "HTTPHeaderNames.h"
#include "InspectorInstrumentation.h"
#include "LoaderStrategy.h"
#include "Logging.h"
#include "MemoryCache.h"
#include "PlatformStrategies.h"
#include "ProgressTracker.h"
#include "ResourceHandle.h"
#include "SchemeRegistry.h"
#include "SecurityOrigin.h"
#include "SubresourceLoader.h"
#include "URL.h"
#include <wtf/CompletionHandler.h>
#include <wtf/MathExtras.h>
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
#include <wtf/text/CString.h>

#if USE(QUICK_LOOK)
#include "QuickLook.h"
#endif


#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(cachedResourceLoader.isAlwaysOnLoggingAllowed(), Network, "%p - CachedResource::" fmt, this, ##__VA_ARGS__)

namespace WebCore {
using namespace WTF;

ResourceLoadPriority CachedResource::defaultPriorityForResourceType(Type type)
{
    switch (type) {
    case CachedResource::MainResource:
        return ResourceLoadPriority::VeryHigh;
    case CachedResource::CSSStyleSheet:
    case CachedResource::Script:
        return ResourceLoadPriority::High;
#if ENABLE(SVG_FONTS)
    case CachedResource::SVGFontResource:
#endif
    case CachedResource::MediaResource:
    case CachedResource::FontResource:
    case CachedResource::RawResource:
    case CachedResource::Icon:
        return ResourceLoadPriority::Medium;
    case CachedResource::ImageResource:
        return ResourceLoadPriority::Low;
#if ENABLE(XSLT)
    case CachedResource::XSLStyleSheet:
        return ResourceLoadPriority::High;
#endif
    case CachedResource::SVGDocumentResource:
        return ResourceLoadPriority::Low;
    case CachedResource::Beacon:
        return ResourceLoadPriority::VeryLow;
    case CachedResource::LinkPrefetch:
        return ResourceLoadPriority::VeryLow;
#if ENABLE(VIDEO_TRACK)
    case CachedResource::TextTrackResource:
        return ResourceLoadPriority::Low;
#endif
#if ENABLE(APPLICATION_MANIFEST)
    case CachedResource::ApplicationManifest:
        return ResourceLoadPriority::Low;
#endif
    }
    ASSERT_NOT_REACHED();
    return ResourceLoadPriority::Low;
}

static Seconds deadDecodedDataDeletionIntervalForResourceType(CachedResource::Type type)
{
    if (type == CachedResource::Script)
        return 0_s;

    return MemoryCache::singleton().deadDecodedDataDeletionInterval();
}

DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, cachedResourceLeakCounter, ("CachedResource"));

CachedResource::CachedResource(CachedResourceRequest&& request, Type type, PAL::SessionID sessionID)
    : m_resourceRequest(request.releaseResourceRequest())
    , m_options(request.options())
    , m_decodedDataDeletionTimer(*this, &CachedResource::destroyDecodedData, deadDecodedDataDeletionIntervalForResourceType(type))
    , m_sessionID(sessionID)
    , m_loadPriority(defaultPriorityForResourceType(type))
    , m_responseTimestamp(WallTime::now())
    , m_fragmentIdentifierForRequest(request.releaseFragmentIdentifier())
    , m_origin(request.releaseOrigin())
    , m_initiatorName(request.initiatorName())
    , m_isLinkPreload(request.isLinkPreload())
    , m_hasUnknownEncoding(request.isLinkPreload())
    , m_type(type)
    , m_ignoreForRequestCount(request.ignoreForRequestCount())
{
    ASSERT(sessionID.isValid());

    setLoadPriority(request.priority());
#ifndef NDEBUG
    cachedResourceLeakCounter.increment();
#endif

    // FIXME: We should have a better way of checking for Navigation loads, maybe FetchMode::Options::Navigate.
    ASSERT(m_origin || m_type == CachedResource::MainResource);

    if (isRequestCrossOrigin(m_origin.get(), m_resourceRequest.url(), m_options))
        setCrossOrigin();
}

// FIXME: For this constructor, we should probably mandate that the URL has no fragment identifier.
CachedResource::CachedResource(const URL& url, Type type, PAL::SessionID sessionID)
    : m_resourceRequest(url)
    , m_decodedDataDeletionTimer(*this, &CachedResource::destroyDecodedData, deadDecodedDataDeletionIntervalForResourceType(type))
    , m_sessionID(sessionID)
    , m_responseTimestamp(WallTime::now())
    , m_fragmentIdentifierForRequest(CachedResourceRequest::splitFragmentIdentifierFromRequestURL(m_resourceRequest))
    , m_type(type)
    , m_status(Cached)
{
    ASSERT(sessionID.isValid());
#ifndef NDEBUG
    cachedResourceLeakCounter.increment();
#endif
}

CachedResource::~CachedResource()
{
    ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() checks this.
    ASSERT(canDelete());
    ASSERT(!inCache());
    ASSERT(!m_deleted);
    ASSERT(url().isNull() || !allowsCaching() || MemoryCache::singleton().resourceForRequest(resourceRequest(), sessionID()) != this);

#ifndef NDEBUG
    m_deleted = true;
    cachedResourceLeakCounter.decrement();
#endif

    if (m_owningCachedResourceLoader)
        m_owningCachedResourceLoader->removeCachedResource(*this);
}

void CachedResource::failBeforeStarting()
{
    // FIXME: What if resources in other frames were waiting for this revalidation?
    LOG(ResourceLoading, "Cannot start loading '%s'", url().string().latin1().data());
    if (allowsCaching() && m_resourceToRevalidate)
        MemoryCache::singleton().revalidationFailed(*this);
    error(CachedResource::LoadError);
}

void CachedResource::load(CachedResourceLoader& cachedResourceLoader)
{
    if (!cachedResourceLoader.frame()) {
        RELEASE_LOG_IF_ALLOWED("load: No associated frame");
        failBeforeStarting();
        return;
    }
    Frame& frame = *cachedResourceLoader.frame();

    // Prevent new loads if we are in the PageCache or being added to the PageCache.
    // We query the top document because new frames may be created in pagehide event handlers
    // and their pageCacheState will not reflect the fact that they are about to enter page
    // cache.
    if (auto* topDocument = frame.mainFrame().document()) {
        if (topDocument->pageCacheState() != Document::NotInPageCache) {
            RELEASE_LOG_IF_ALLOWED("load: Already in page cache or being added to it (frame = %p)", &frame);
            failBeforeStarting();
            return;
        }
    }

    FrameLoader& frameLoader = frame.loader();
    if (m_options.securityCheck == DoSecurityCheck && (frameLoader.state() == FrameStateProvisional || !frameLoader.activeDocumentLoader() || frameLoader.activeDocumentLoader()->isStopping())) {
        if (frameLoader.state() == FrameStateProvisional)
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- state is provisional (frame = %p)", &frame);
        else if (!frameLoader.activeDocumentLoader())
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- not active document (frame = %p)", &frame);
        else if (frameLoader.activeDocumentLoader()->isStopping())
            RELEASE_LOG_IF_ALLOWED("load: Failed security check -- active loader is stopping (frame = %p)", &frame);
        failBeforeStarting();
        return;
    }

    m_loading = true;

    if (isCacheValidator()) {
        CachedResource* resourceToRevalidate = m_resourceToRevalidate;
        ASSERT(resourceToRevalidate->canUseCacheValidator());
        ASSERT(resourceToRevalidate->isLoaded());
        const String& lastModified = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::LastModified);
        const String& eTag = resourceToRevalidate->response().httpHeaderField(HTTPHeaderName::ETag);
        if (!lastModified.isEmpty() || !eTag.isEmpty()) {
            ASSERT(cachedResourceLoader.cachePolicy(type(), url()) != CachePolicyReload);
            if (cachedResourceLoader.cachePolicy(type(), url()) == CachePolicyRevalidate)
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
            if (!lastModified.isEmpty())
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified);
            if (!eTag.isEmpty())
                m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag);
        }
    }

    if (type() == CachedResource::LinkPrefetch)
        m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::Purpose, "prefetch");
    m_resourceRequest.setPriority(loadPriority());

    // Navigation algorithm is setting up the request before sending it to CachedResourceLoader?CachedResource.
    // So no need for extra fields for MainResource.
    if (type() != CachedResource::MainResource)
        frameLoader.addExtraFieldsToSubresourceRequest(m_resourceRequest);


    // FIXME: It's unfortunate that the cache layer and below get to know anything about fragment identifiers.
    // We should look into removing the expectation of that knowledge from the platform network stacks.
    ResourceRequest request(m_resourceRequest);
    if (!m_fragmentIdentifierForRequest.isNull()) {
        URL url = request.url();
        url.setFragmentIdentifier(m_fragmentIdentifierForRequest);
        request.setURL(url);
        m_fragmentIdentifierForRequest = String();
    }

    if (m_options.keepAlive) {
        if (!cachedResourceLoader.keepaliveRequestTracker().tryRegisterRequest(*this)) {
            setResourceError({ errorDomainWebKitInternal, 0, request.url(), ASCIILiteral("Reached maximum amount of queued data of 64Kb for keepalive requests"), ResourceError::Type::AccessControl });
            failBeforeStarting();
            return;
        }
        // FIXME: We should not special-case Beacon here.
        if (shouldUsePingLoad(type())) {
            ASSERT(m_originalRequest);
            CachedResourceHandle<CachedResource> protectedThis(this);

            // FIXME: Move beacon loads to normal subresource loading to get normal inspector request instrumentation hooks.
            unsigned long identifier = frame.page()->progress().createUniqueIdentifier();
            InspectorInstrumentation::willSendRequestOfType(&frame, identifier, frameLoader.activeDocumentLoader(), request, InspectorInstrumentation::LoadType::Beacon);

            platformStrategies()->loaderStrategy()->startPingLoad(frame, request, m_originalRequest->httpHeaderFields(), m_options, [this, protectedThis = WTFMove(protectedThis), protectedFrame = makeRef(frame), identifier] (const ResourceError& error, const ResourceResponse& response) {
                if (!response.isNull())
                    InspectorInstrumentation::didReceiveResourceResponse(protectedFrame, identifier, protectedFrame->loader().activeDocumentLoader(), response, nullptr);
                if (error.isNull()) {
                    finishLoading(nullptr);
                    NetworkLoadMetrics emptyMetrics;
                    InspectorInstrumentation::didFinishLoading(protectedFrame.ptr(), protectedFrame->loader().activeDocumentLoader(), identifier, emptyMetrics, nullptr);
                } else {
                    setResourceError(error);
                    this->error(LoadError);
                    InspectorInstrumentation::didFailLoading(protectedFrame.ptr(), protectedFrame->loader().activeDocumentLoader(), identifier, error);
                }
            });
            return;
        }
    }

    platformStrategies()->loaderStrategy()->loadResource(frame, *this, WTFMove(request), m_options, [this, protectedThis = CachedResourceHandle<CachedResource>(this), frame = makeRef(frame), loggingAllowed = cachedResourceLoader.isAlwaysOnLoggingAllowed()] (RefPtr<SubresourceLoader>&& loader) {
        m_loader = WTFMove(loader);
        if (!m_loader) {
            RELEASE_LOG_IF(loggingAllowed, Network, "%p - CachedResource::load: Unable to create SubresourceLoader (frame = %p)", this, frame.ptr());
            failBeforeStarting();
            return;
        }
        m_status = Pending;
    });
}

void CachedResource::loadFrom(const CachedResource& resource)
{
    ASSERT(url() == resource.url());
    ASSERT(type() == resource.type());
    ASSERT(resource.status() == Status::Cached);

    if (isCrossOrigin() && m_options.mode == FetchOptions::Mode::Cors) {
        ASSERT(m_origin);
        String errorMessage;
        if (!WebCore::passesAccessControlCheck(resource.response(), m_options.storedCredentialsPolicy, *m_origin, errorMessage)) {
            setResourceError(ResourceError(String(), 0, url(), errorMessage, ResourceError::Type::AccessControl));
            return;
        }
    }

    setBodyDataFrom(resource);
    setStatus(Status::Cached);
    setLoading(false);
}

void CachedResource::setBodyDataFrom(const CachedResource& resource)
{
    m_data = resource.m_data;
    m_response = resource.m_response;
    m_response.setTainting(m_responseTainting);
    setDecodedSize(resource.decodedSize());
    setEncodedSize(resource.encodedSize());
}

void CachedResource::checkNotify()
{
    if (isLoading() || stillNeedsLoad())
        return;

    CachedResourceClientWalker<CachedResourceClient> walker(m_clients);
    while (CachedResourceClient* client = walker.next())
        client->notifyFinished(*this);
}

void CachedResource::updateBuffer(SharedBuffer&)
{
    ASSERT(dataBufferingPolicy() == BufferData);
}

void CachedResource::updateData(const char*, unsigned)
{
    ASSERT(dataBufferingPolicy() == DoNotBufferData);
}

void CachedResource::finishLoading(SharedBuffer*)
{
    setLoading(false);
    checkNotify();
}

void CachedResource::error(CachedResource::Status status)
{
    setStatus(status);
    ASSERT(errorOccurred());
    m_data = nullptr;

    setLoading(false);
    checkNotify();
}
    
void CachedResource::cancelLoad()
{
    if (!isLoading() && !stillNeedsLoad())
        return;

    setStatus(LoadError);
    setLoading(false);
    checkNotify();
}

void CachedResource::finish()
{
    if (!errorOccurred())
        m_status = Cached;
}

void CachedResource::setCrossOrigin()
{
    ASSERT(m_options.mode != FetchOptions::Mode::SameOrigin);
    m_responseTainting = (m_options.mode == FetchOptions::Mode::Cors) ? ResourceResponse::Tainting::Cors : ResourceResponse::Tainting::Opaque;
}

bool CachedResource::isCrossOrigin() const
{
    return m_responseTainting != ResourceResponse::Tainting::Basic;
}

bool CachedResource::isCORSSameOrigin() const
{
    // Following resource types do not use CORS
    ASSERT(type() != CachedResource::Type::FontResource);
#if ENABLE(SVG_FONTS)
    ASSERT(type() != CachedResource::Type::SVGFontResource);
#endif
#if ENABLE(XSLT)
    ASSERT(type() != CachedResource::XSLStyleSheet);
#endif

    // https://html.spec.whatwg.org/multipage/infrastructure.html#cors-same-origin
    return !loadFailedOrCanceled() && m_responseTainting != ResourceResponse::Tainting::Opaque;
}

bool CachedResource::isExpired() const
{
    if (m_response.isNull())
        return false;

    return computeCurrentAge(m_response, m_responseTimestamp) > freshnessLifetime(m_response);
}

static inline bool shouldCacheSchemeIndefinitely(StringView scheme)
{
#if PLATFORM(COCOA)
    if (equalLettersIgnoringASCIICase(scheme, "applewebdata"))
        return true;
#endif
#if USE(SOUP)
    if (equalLettersIgnoringASCIICase(scheme, "resource"))
        return true;
#endif
    return equalLettersIgnoringASCIICase(scheme, "data");
}

Seconds CachedResource::freshnessLifetime(const ResourceResponse& response) const
{
    if (!response.url().protocolIsInHTTPFamily()) {
        StringView protocol = response.url().protocol();
        if (!shouldCacheSchemeIndefinitely(protocol)) {
            // Don't cache non-HTTP main resources since we can't check for freshness.
            // FIXME: We should not cache subresources either, but when we tried this
            // it caused performance and flakiness issues in our test infrastructure.
            if (m_type == MainResource || SchemeRegistry::shouldAlwaysRevalidateURLScheme(protocol.toStringWithoutCopying()))
                return 0_us;
        }

        return Seconds::infinity();
    }

    return computeFreshnessLifetimeForHTTPFamily(response, m_responseTimestamp);
}

void CachedResource::redirectReceived(ResourceRequest&& request, const ResourceResponse& response, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
{
    m_requestedFromNetworkingLayer = true;
    if (response.isNull())
        return completionHandler(WTFMove(request));

    updateRedirectChainStatus(m_redirectChainCacheStatus, response);
    completionHandler(WTFMove(request));
}

void CachedResource::setResponse(const ResourceResponse& response)
{
    ASSERT(m_response.type() == ResourceResponse::Type::Default);
    m_response = response;
    m_varyingHeaderValues = collectVaryingRequestHeaders(m_resourceRequest, m_response, m_sessionID);

#if ENABLE(SERVICE_WORKER)
    if (m_response.source() == ResourceResponse::Source::ServiceWorker) {
        m_responseTainting = m_response.tainting();
        return;
    }
#endif
    m_response.setRedirected(m_redirectChainCacheStatus.status != RedirectChainCacheStatus::NoRedirection);
    if (m_response.tainting() == ResourceResponse::Tainting::Basic || m_response.tainting() == ResourceResponse::Tainting::Cors)
        m_response.setTainting(m_responseTainting);
}

void CachedResource::responseReceived(const ResourceResponse& response)
{
    setResponse(response);
    m_responseTimestamp = WallTime::now();
    String encoding = response.textEncodingName();
    if (!encoding.isNull())
        setEncoding(encoding);
}

void CachedResource::clearLoader()
{
    ASSERT(m_loader);
    m_identifierForLoadWithoutResourceLoader = m_loader->identifier();
    m_loader = nullptr;
    deleteIfPossible();
}

void CachedResource::addClient(CachedResourceClient& client)
{
    if (addClientToSet(client))
        didAddClient(client);
}

void CachedResource::didAddClient(CachedResourceClient& client)
{
    if (m_decodedDataDeletionTimer.isActive())
        m_decodedDataDeletionTimer.stop();

    if (m_clientsAwaitingCallback.remove(&client))
        m_clients.add(&client);
    if (!isLoading() && !stillNeedsLoad())
        client.notifyFinished(*this);
}

bool CachedResource::addClientToSet(CachedResourceClient& client)
{
    if (m_preloadResult == PreloadNotReferenced && client.shouldMarkAsReferenced()) {
        if (isLoaded())
            m_preloadResult = PreloadReferencedWhileComplete;
        else if (m_requestedFromNetworkingLayer)
            m_preloadResult = PreloadReferencedWhileLoading;
        else
            m_preloadResult = PreloadReferenced;
    }
    if (allowsCaching() && !hasClients() && inCache())
        MemoryCache::singleton().addToLiveResourcesSize(*this);

    if ((m_type == RawResource || m_type == MainResource) && !m_response.isNull() && !m_proxyResource) {
        // Certain resources (especially XHRs and main resources) do crazy things if an asynchronous load returns
        // synchronously (e.g., scripts may not have set all the state they need to handle the load).
        // Therefore, rather than immediately sending callbacks on a cache hit like other CachedResources,
        // we schedule the callbacks and ensure we never finish synchronously.
        ASSERT(!m_clientsAwaitingCallback.contains(&client));
        m_clientsAwaitingCallback.add(&client, std::make_unique<Callback>(*this, client));
        return false;
    }

    m_clients.add(&client);
    return true;
}

void CachedResource::removeClient(CachedResourceClient& client)
{
    auto callback = m_clientsAwaitingCallback.take(&client);
    if (callback) {
        ASSERT(!m_clients.contains(&client));
        callback->cancel();
        callback = nullptr;
    } else {
        ASSERT(m_clients.contains(&client));
        m_clients.remove(&client);
        didRemoveClient(client);
    }

    if (deleteIfPossible()) {
        // `this` object is dead here.
        return;
    }

    if (hasClients())
        return;

    auto& memoryCache = MemoryCache::singleton();
    if (allowsCaching() && inCache()) {
        memoryCache.removeFromLiveResourcesSize(*this);
        memoryCache.removeFromLiveDecodedResourcesList(*this);
    }
    if (!m_switchingClientsToRevalidatedResource)
        allClientsRemoved();
    destroyDecodedDataIfNeeded();

    if (!allowsCaching())
        return;

    if (response().cacheControlContainsNoStore() && url().protocolIs("https")) {
        // RFC2616 14.9.2:
        // "no-store: ... MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible"
        // "... History buffers MAY store such responses as part of their normal operation."
        // We allow non-secure content to be reused in history, but we do not allow secure content to be reused.
        memoryCache.remove(*this);
    }
    memoryCache.pruneSoon();
}

void CachedResource::allClientsRemoved()
{
    if (isLinkPreload() && m_loader)
        m_loader->cancelIfNotFinishing();
}

void CachedResource::destroyDecodedDataIfNeeded()
{
    if (!m_decodedSize)
        return;
    if (!MemoryCache::singleton().deadDecodedDataDeletionInterval())
        return;
    m_decodedDataDeletionTimer.restart();
}

void CachedResource::decodedDataDeletionTimerFired()
{
    destroyDecodedData();
}

bool CachedResource::deleteIfPossible()
{
    if (canDelete()) {
        if (!inCache()) {
            InspectorInstrumentation::willDestroyCachedResource(*this);
            delete this;
            return true;
        }
        if (m_data)
            m_data->hintMemoryNotNeededSoon();
    }
    return false;
}

void CachedResource::setDecodedSize(unsigned size)
{
    if (size == m_decodedSize)
        return;

    long long delta = static_cast<long long>(size) - m_decodedSize;

    // The object must be moved to a different queue, since its size has been changed.
    // Remove before updating m_decodedSize, so we find the resource in the correct LRU list.
    if (allowsCaching() && inCache())
        MemoryCache::singleton().removeFromLRUList(*this);

    m_decodedSize = size;
   
    if (allowsCaching() && inCache()) {
        auto& memoryCache = MemoryCache::singleton();
        // Now insert into the new LRU list.
        memoryCache.insertInLRUList(*this);
        
        // Insert into or remove from the live decoded list if necessary.
        // When inserting into the LiveDecodedResourcesList it is possible
        // that the m_lastDecodedAccessTime is still zero or smaller than
        // the m_lastDecodedAccessTime of the current list head. This is a
        // violation of the invariant that the list is to be kept sorted
        // by access time. The weakening of the invariant does not pose
        // a problem. For more details please see: https://bugs.webkit.org/show_bug.cgi?id=30209
        bool inLiveDecodedResourcesList = memoryCache.inLiveDecodedResourcesList(*this);
        if (m_decodedSize && !inLiveDecodedResourcesList && hasClients())
            memoryCache.insertInLiveDecodedResourcesList(*this);
        else if (!m_decodedSize && inLiveDecodedResourcesList)
            memoryCache.removeFromLiveDecodedResourcesList(*this);

        // Update the cache's size totals.
        memoryCache.adjustSize(hasClients(), delta);
    }
}

void CachedResource::setEncodedSize(unsigned size)
{
    if (size == m_encodedSize)
        return;

    long long delta = static_cast<long long>(size) - m_encodedSize;

    // The object must be moved to a different queue, since its size has been changed.
    // Remove before updating m_encodedSize, so we find the resource in the correct LRU list.
    if (allowsCaching() && inCache())
        MemoryCache::singleton().removeFromLRUList(*this);

    m_encodedSize = size;

    if (allowsCaching() && inCache()) {
        auto& memoryCache = MemoryCache::singleton();
        memoryCache.insertInLRUList(*this);
        memoryCache.adjustSize(hasClients(), delta);
    }
}

void CachedResource::didAccessDecodedData(MonotonicTime timeStamp)
{
    m_lastDecodedAccessTime = timeStamp;
    
    if (allowsCaching() && inCache()) {
        auto& memoryCache = MemoryCache::singleton();
        if (memoryCache.inLiveDecodedResourcesList(*this)) {
            memoryCache.removeFromLiveDecodedResourcesList(*this);
            memoryCache.insertInLiveDecodedResourcesList(*this);
        }
        memoryCache.pruneSoon();
    }
}
    
void CachedResource::setResourceToRevalidate(CachedResource* resource) 
{ 
    ASSERT(resource);
    ASSERT(!m_resourceToRevalidate);
    ASSERT(resource != this);
    ASSERT(m_handlesToRevalidate.isEmpty());
    ASSERT(resource->type() == type());
    ASSERT(!resource->m_proxyResource);

    LOG(ResourceLoading, "CachedResource %p setResourceToRevalidate %p", this, resource);

    resource->m_proxyResource = this;
    m_resourceToRevalidate = resource;
}

void CachedResource::clearResourceToRevalidate() 
{
    ASSERT(m_resourceToRevalidate);
    ASSERT(m_resourceToRevalidate->m_proxyResource == this);

    if (m_switchingClientsToRevalidatedResource)
        return;

    m_resourceToRevalidate->m_proxyResource = nullptr;
    m_resourceToRevalidate->deleteIfPossible();

    m_handlesToRevalidate.clear();
    m_resourceToRevalidate = nullptr;
    deleteIfPossible();
}
    
void CachedResource::switchClientsToRevalidatedResource()
{
    ASSERT(m_resourceToRevalidate);
    ASSERT(m_resourceToRevalidate->inCache());
    ASSERT(!inCache());

    LOG(ResourceLoading, "CachedResource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate);

    m_switchingClientsToRevalidatedResource = true;
    for (auto& handle : m_handlesToRevalidate) {
        handle->m_resource = m_resourceToRevalidate;
        m_resourceToRevalidate->registerHandle(handle);
        --m_handleCount;
    }
    ASSERT(!m_handleCount);
    m_handlesToRevalidate.clear();

    Vector<CachedResourceClient*> clientsToMove;
    for (auto& entry : m_clients) {
        CachedResourceClient* client = entry.key;
        unsigned count = entry.value;
        while (count) {
            clientsToMove.append(client);
            --count;
        }
    }

    for (auto& client : clientsToMove)
        removeClient(*client);
    ASSERT(m_clients.isEmpty());

    for (auto& client : clientsToMove)
        m_resourceToRevalidate->addClientToSet(*client);
    for (auto& client : clientsToMove) {
        // Calling didAddClient may do anything, including trying to cancel revalidation.
        // Assert that it didn't succeed.
        ASSERT(m_resourceToRevalidate);
        // Calling didAddClient for a client may end up removing another client. In that case it won't be in the set anymore.
        if (m_resourceToRevalidate->m_clients.contains(client))
            m_resourceToRevalidate->didAddClient(*client);
    }
    m_switchingClientsToRevalidatedResource = false;
}

void CachedResource::updateResponseAfterRevalidation(const ResourceResponse& validatingResponse)
{
    m_responseTimestamp = WallTime::now();

    updateResponseHeadersAfterRevalidation(m_response, validatingResponse);
}

void CachedResource::registerHandle(CachedResourceHandleBase* h)
{
    ++m_handleCount;
    if (m_resourceToRevalidate)
        m_handlesToRevalidate.add(h);
}

void CachedResource::unregisterHandle(CachedResourceHandleBase* h)
{
    ASSERT(m_handleCount > 0);
    --m_handleCount;

    if (m_resourceToRevalidate)
         m_handlesToRevalidate.remove(h);

    if (!m_handleCount)
        deleteIfPossible();
}

bool CachedResource::canUseCacheValidator() const
{
    if (m_loading || errorOccurred())
        return false;

    if (m_response.cacheControlContainsNoStore())
        return false;
    return m_response.hasCacheValidatorFields();
}

CachedResource::RevalidationDecision CachedResource::makeRevalidationDecision(CachePolicy cachePolicy) const
{    
    switch (cachePolicy) {
    case CachePolicyHistoryBuffer:
        return RevalidationDecision::No;

    case CachePolicyReload:
        return RevalidationDecision::YesDueToCachePolicy;

    case CachePolicyRevalidate:
        if (m_response.cacheControlContainsImmutable() && m_response.url().protocolIs("https")) {
            if (isExpired())
                return RevalidationDecision::YesDueToExpired;
            return RevalidationDecision::No;
        }
        return RevalidationDecision::YesDueToCachePolicy;

    case CachePolicyVerify:
        if (m_response.cacheControlContainsNoCache())
            return RevalidationDecision::YesDueToNoCache;
        // FIXME: Cache-Control:no-store should prevent storing, not reuse.
        if (m_response.cacheControlContainsNoStore())
            return RevalidationDecision::YesDueToNoStore;

        if (isExpired())
            return RevalidationDecision::YesDueToExpired;

        return RevalidationDecision::No;
    };
    ASSERT_NOT_REACHED();
    return RevalidationDecision::No;
}

bool CachedResource::redirectChainAllowsReuse(ReuseExpiredRedirectionOrNot reuseExpiredRedirection) const
{
    return WebCore::redirectChainAllowsReuse(m_redirectChainCacheStatus, reuseExpiredRedirection);
}

bool CachedResource::varyHeaderValuesMatch(const ResourceRequest& request)
{
    if (m_varyingHeaderValues.isEmpty())
        return true;

    return verifyVaryingRequestHeaders(m_varyingHeaderValues, request, m_sessionID);
}

unsigned CachedResource::overheadSize() const
{
    static const int kAverageClientsHashMapSize = 384;
    return sizeof(CachedResource) + m_response.memoryUsage() + kAverageClientsHashMapSize + m_resourceRequest.url().string().length() * 2;
}

bool CachedResource::areAllClientsXMLHttpRequests() const
{
    if (type() != RawResource)
        return false;

    for (auto& client : m_clients) {
        if (!client.key->isXMLHttpRequest())
            return false;
    }
    return true;
}

void CachedResource::setLoadPriority(const std::optional<ResourceLoadPriority>& loadPriority)
{
    if (loadPriority)
        m_loadPriority = loadPriority.value();
    else
        m_loadPriority = defaultPriorityForResourceType(type());
}

inline CachedResource::Callback::Callback(CachedResource& resource, CachedResourceClient& client)
    : m_resource(resource)
    , m_client(client)
    , m_timer(*this, &Callback::timerFired)
{
    m_timer.startOneShot(0_s);
}

inline void CachedResource::Callback::cancel()
{
    if (m_timer.isActive())
        m_timer.stop();
}

void CachedResource::Callback::timerFired()
{
    m_resource.didAddClient(m_client);
}

#if USE(FOUNDATION) || USE(SOUP)

void CachedResource::tryReplaceEncodedData(SharedBuffer& newBuffer)
{
    if (!m_data)
        return;
    
    if (!mayTryReplaceEncodedData())
        return;

    // We have to do the memcmp because we can't tell if the replacement file backed data is for the
    // same resource or if we made a second request with the same URL which gave us a different
    // resource. We have seen this happen for cached POST resources.
    if (m_data->size() != newBuffer.size() || memcmp(m_data->data(), newBuffer.data(), m_data->size()))
        return;

    m_data->clear();
    m_data->append(newBuffer);
    didReplaceSharedBufferContents();
}

#endif

}
