/*
    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, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 "core/fetch/Resource.h"

#include "core/FetchInitiatorTypeNames.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/ResourceClient.h"
#include "core/fetch/ResourceClientWalker.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/ResourceLoader.h"
#include "core/fetch/ResourcePtr.h"
#include "platform/Logging.h"
#include "platform/SharedBuffer.h"
#include "platform/TraceEvent.h"
#include "platform/weborigin/KURL.h"
#include "public/platform/Platform.h"
#include "wtf/CurrentTime.h"
#include "wtf/MathExtras.h"
#include "wtf/RefCountedLeakCounter.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Vector.h"
#include "wtf/text/CString.h"

using namespace WTF;

namespace blink {

// These response headers are not copied from a revalidated response to the
// cached response headers. For compatibility, this list is based on Chromium's
// net/http/http_response_headers.cc.
const char* const headersToIgnoreAfterRevalidation[] = {
    "allow",
    "connection",
    "etag",
    "expires",
    "keep-alive",
    "last-modified"
    "proxy-authenticate",
    "proxy-connection",
    "trailer",
    "transfer-encoding",
    "upgrade",
    "www-authenticate",
    "x-frame-options",
    "x-xss-protection",
};

// Some header prefixes mean "Don't copy this header from a 304 response.".
// Rather than listing all the relevant headers, we can consolidate them into
// this list, also grabbed from Chromium's net/http/http_response_headers.cc.
const char* const headerPrefixesToIgnoreAfterRevalidation[] = {
    "content-",
    "x-content-",
    "x-webkit-"
};

static inline bool shouldUpdateHeaderAfterRevalidation(const AtomicString& header)
{
    for (size_t i = 0; i < WTF_ARRAY_LENGTH(headersToIgnoreAfterRevalidation); i++) {
        if (equalIgnoringCase(header, headersToIgnoreAfterRevalidation[i]))
            return false;
    }
    for (size_t i = 0; i < WTF_ARRAY_LENGTH(headerPrefixesToIgnoreAfterRevalidation); i++) {
        if (header.startsWith(headerPrefixesToIgnoreAfterRevalidation[i], false))
            return false;
    }
    return true;
}

DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, cachedResourceLeakCounter, ("Resource"));
unsigned Resource::s_instanceCount = 0;

Resource::Resource(const ResourceRequest& request, Type type)
    : m_resourceRequest(request)
    , m_responseTimestamp(currentTime())
    , m_cancelTimer(this, &Resource::cancelTimerFired)
    , m_loadFinishTime(0)
    , m_identifier(0)
    , m_encodedSize(0)
    , m_decodedSize(0)
    , m_handleCount(0)
    , m_preloadCount(0)
    , m_protectorCount(0)
    , m_preloadResult(PreloadNotReferenced)
    , m_requestedFromNetworkingLayer(false)
    , m_loading(false)
    , m_switchingClientsToRevalidatedResource(false)
    , m_type(type)
    , m_status(Pending)
    , m_wasPurged(false)
    , m_needsSynchronousCacheHit(false)
#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
    , m_deleted(false)
#endif
    , m_resourceToRevalidate(nullptr)
    , m_proxyResource(nullptr)
{
    ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests careless updates of the enum.
    ++s_instanceCount;
#ifndef NDEBUG
    cachedResourceLeakCounter.increment();
#endif
    memoryCache()->registerLiveResource(*this);

    if (!m_resourceRequest.url().hasFragmentIdentifier())
        return;
    KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceRequest.url());
    if (urlForCache.hasFragmentIdentifier())
        return;
    m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier();
    m_resourceRequest.setURL(urlForCache);
}

Resource::~Resource()
{
    ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() checks this.
    ASSERT(canDelete());
    RELEASE_ASSERT(!memoryCache()->contains(this));
    RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this));
    ASSERT(url().isNull() || memoryCache()->resourceForURL(KURL(ParsedURLString, url())) != this);
    assertAlive();

#ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
    m_deleted = true;
#endif
#ifndef NDEBUG
    cachedResourceLeakCounter.decrement();
#endif
    --s_instanceCount;
}

void Resource::dispose()
{
}

void Resource::trace(Visitor* visitor)
{
    visitor->trace(m_loader);
    visitor->trace(m_resourceToRevalidate);
    visitor->trace(m_proxyResource);
}

void Resource::failBeforeStarting()
{
    WTF_LOG(ResourceLoading, "Cannot start loading '%s'", url().string().latin1().data());
    error(Resource::LoadError);
}

void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& options)
{
    if (!fetcher->frame()) {
        failBeforeStarting();
        return;
    }

    m_options = options;
    m_loading = true;

    if (!accept().isEmpty())
        m_resourceRequest.setHTTPAccept(accept());

    // 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()) {
        KURL url = request.url();
        url.setFragmentIdentifier(m_fragmentIdentifierForRequest);
        request.setURL(url);
        m_fragmentIdentifierForRequest = String();
    }
    m_status = Pending;
    m_loader = ResourceLoader::create(fetcher, this, request, options);
    m_loader->start();
}

void Resource::checkNotify()
{
    if (isLoading())
        return;

    ResourceClientWalker<ResourceClient> w(m_clients);
    while (ResourceClient* c = w.next())
        c->notifyFinished(this);
}

void Resource::appendData(const char* data, int length)
{
    TRACE_EVENT0("blink", "Resource::appendData");
    ASSERT(!m_resourceToRevalidate);
    ASSERT(!errorOccurred());
    if (m_options.dataBufferingPolicy == DoNotBufferData)
        return;
    if (m_data)
        m_data->append(data, length);
    else
        m_data = SharedBuffer::createPurgeable(data, length);
    setEncodedSize(m_data->size());
}

void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer)
{
    ASSERT(!m_resourceToRevalidate);
    ASSERT(!errorOccurred());
    ASSERT(m_options.dataBufferingPolicy == BufferData);
    m_data = resourceBuffer;
    setEncodedSize(m_data->size());
}

void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
{
    m_options.dataBufferingPolicy = dataBufferingPolicy;
    m_data.clear();
    setEncodedSize(0);
}

void Resource::error(Resource::Status status)
{
    if (m_resourceToRevalidate)
        revalidationFailed();

    if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded()))
        memoryCache()->remove(this);

    setStatus(status);
    ASSERT(errorOccurred());
    m_data.clear();

    setLoading(false);
    checkNotify();
}

void Resource::finishOnePart()
{
    setLoading(false);
    checkNotify();
}

void Resource::finish(double finishTime)
{
    ASSERT(!m_resourceToRevalidate);
    ASSERT(!errorOccurred());
    m_loadFinishTime = finishTime;
    finishOnePart();
    if (!errorOccurred())
        m_status = Cached;
}

static double currentAge(const ResourceResponse& response, double responseTimestamp)
{
    // RFC2616 13.2.3
    // No compensation for latency as that is not terribly important in practice
    double dateValue = response.date();
    double apparentAge = std::isfinite(dateValue) ? std::max(0., responseTimestamp - dateValue) : 0;
    double ageValue = response.age();
    double correctedReceivedAge = std::isfinite(ageValue) ? std::max(apparentAge, ageValue) : apparentAge;
    double residentTime = currentTime() - responseTimestamp;
    return correctedReceivedAge + residentTime;
}

static double freshnessLifetime(ResourceResponse& response, double responseTimestamp)
{
#if !OS(ANDROID)
    // On desktop, local files should be reloaded in case they change.
    if (response.url().isLocalFile())
        return 0;
#endif

    // Cache other non-http / non-filesystem resources liberally.
    if (!response.url().protocolIsInHTTPFamily()
        && !response.url().protocolIs("filesystem"))
        return std::numeric_limits<double>::max();

    // RFC2616 13.2.4
    double maxAgeValue = response.cacheControlMaxAge();
    if (std::isfinite(maxAgeValue))
        return maxAgeValue;
    double expiresValue = response.expires();
    double dateValue = response.date();
    double creationTime = std::isfinite(dateValue) ? dateValue : responseTimestamp;
    if (std::isfinite(expiresValue))
        return expiresValue - creationTime;
    double lastModifiedValue = response.lastModified();
    if (std::isfinite(lastModifiedValue))
        return (creationTime - lastModifiedValue) * 0.1;
    // If no cache headers are present, the specification leaves the decision to the UA. Other browsers seem to opt for 0.
    return 0;
}

static bool canUseResponse(ResourceResponse& response, double responseTimestamp)
{
    if (response.isNull())
        return false;

    // FIXME: Why isn't must-revalidate considered a reason we can't use the response?
    if (response.cacheControlContainsNoCache() || response.cacheControlContainsNoStore())
        return false;

    if (response.httpStatusCode() == 303)  {
        // Must not be cached.
        return false;
    }

    if (response.httpStatusCode() == 302 || response.httpStatusCode() == 307) {
        // Default to not cacheable unless explicitly allowed.
        bool hasMaxAge = std::isfinite(response.cacheControlMaxAge());
        bool hasExpires = std::isfinite(response.expires());
        // TODO: consider catching Cache-Control "private" and "public" here.
        if (!hasMaxAge && !hasExpires)
            return false;
    }

    return currentAge(response, responseTimestamp) <= freshnessLifetime(response, responseTimestamp);
}

void Resource::willSendRequest(ResourceRequest& request, const ResourceResponse& response)
{
    m_requestedFromNetworkingLayer = true;
}

bool Resource::unlock()
{
    if (!m_data)
        return false;

    if (!m_data->isLocked())
        return true;

    if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || m_proxyResource || m_resourceToRevalidate || !m_loadFinishTime || !isSafeToUnlock())
        return false;

    m_data->unlock();
    return true;
}

bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const
{
    return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0);
}

void Resource::responseReceived(const ResourceResponse& response)
{
    setResponse(response);
    m_responseTimestamp = currentTime();
    String encoding = response.textEncodingName();
    if (!encoding.isNull())
        setEncoding(encoding);

    if (!m_resourceToRevalidate)
        return;
    if (response.httpStatusCode() == 304)
        revalidationSucceeded(response);
    else
        revalidationFailed();
}

bool Resource::canDelete() const
{
    return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountApartFromCache(0)
        && !m_protectorCount && !m_resourceToRevalidate && !m_proxyResource;
}

bool Resource::hasOneHandle() const
{
    return hasRightHandleCountApartFromCache(1);
}

void Resource::clearLoader()
{
    m_loader = nullptr;
}

void Resource::addClient(ResourceClient* client)
{
    if (addClientToSet(client))
        didAddClient(client);
}

void Resource::didAddClient(ResourceClient* c)
{
    if (!isLoading() && !stillNeedsLoad())
        c->notifyFinished(this);
}

static bool shouldSendCachedDataSynchronouslyForType(Resource::Type type)
{
    // Some resources types default to return data synchronously.
    // For most of these, it's because there are layout tests that
    // expect data to return synchronously in case of cache hit. In
    // the case of fonts, there was a performance regression.
    // FIXME: Get to the point where we don't need to special-case sync/async
    // behavior for different resource types.
    if (type == Resource::Image)
        return true;
    if (type == Resource::Font)
        return true;
    return false;
}

bool Resource::addClientToSet(ResourceClient* client)
{
    ASSERT(!isPurgeable());

    if (m_preloadResult == PreloadNotReferenced) {
        if (isLoaded())
            m_preloadResult = PreloadReferencedWhileComplete;
        else if (m_requestedFromNetworkingLayer)
            m_preloadResult = PreloadReferencedWhileLoading;
        else
            m_preloadResult = PreloadReferenced;
    }
    if (!hasClients())
        memoryCache()->makeLive(this);

    // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously.
    if (!m_response.isNull() && !m_proxyResource && !shouldSendCachedDataSynchronouslyForType(type()) && !m_needsSynchronousCacheHit) {
        m_clientsAwaitingCallback.add(client);
        ResourceCallback::callbackHandler()->schedule(this);
        return false;
    }

    m_clients.add(client);
    return true;
}

void Resource::removeClient(ResourceClient* client)
{
    if (m_clientsAwaitingCallback.contains(client)) {
        ASSERT(!m_clients.contains(client));
        m_clientsAwaitingCallback.remove(client);
    } else {
        ASSERT(m_clients.contains(client));
        m_clients.remove(client);
        didRemoveClient(client);
    }

    if (m_clientsAwaitingCallback.isEmpty())
        ResourceCallback::callbackHandler()->cancel(this);

    bool deleted = deleteIfPossible();
    if (!deleted && !hasClients()) {
        memoryCache()->makeDead(this);
        if (!m_switchingClientsToRevalidatedResource)
            allClientsRemoved();

        // 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.
        if (hasCacheControlNoStoreHeader() && url().protocolIs("https")) {
            memoryCache()->remove(this);
            memoryCache()->prune();
        } else {
            memoryCache()->prune(this);
        }
    }
    // This object may be dead here.
}

void Resource::allClientsRemoved()
{
    if (!m_loader)
        return;
    if (m_type == MainResource || m_type == Raw)
        cancelTimerFired(&m_cancelTimer);
    else if (!m_cancelTimer.isActive())
        m_cancelTimer.startOneShot(0, FROM_HERE);

    unlock();
}

void Resource::cancelTimerFired(Timer<Resource>* timer)
{
    ASSERT_UNUSED(timer, timer == &m_cancelTimer);
    if (hasClients() || !m_loader)
        return;
    ResourcePtr<Resource> protect(this);
    m_loader->cancelIfNotFinishing();
    if (m_status != Cached)
        memoryCache()->remove(this);
}

bool Resource::deleteIfPossible()
{
    if (canDelete() && !memoryCache()->contains(this)) {
        dispose();
        memoryCache()->unregisterLiveResource(*this);
#if !ENABLE(OILPAN)
        delete this;
#endif
        return true;
    }
    return false;
}

void Resource::setDecodedSize(size_t decodedSize)
{
    if (decodedSize == m_decodedSize)
        return;
    size_t oldSize = size();
    m_decodedSize = decodedSize;
    memoryCache()->update(this, oldSize, size());
    memoryCache()->updateDecodedResource(this, UpdateForPropertyChange);
}

void Resource::setEncodedSize(size_t encodedSize)
{
    if (encodedSize == m_encodedSize)
        return;
    size_t oldSize = size();
    m_encodedSize = encodedSize;
    memoryCache()->update(this, oldSize, size());
}

void Resource::didAccessDecodedData()
{
    memoryCache()->updateDecodedResource(this, UpdateForAccess);
    memoryCache()->prune();
}

void Resource::finishPendingClients()
{
    // We're going to notify clients one by one. It is simple if the client does nothing.
    // However there are a couple other things that can happen.
    //
    // 1. Clients can be added during the loop. Make sure they are not processed.
    // 2. Clients can be removed during the loop. Make sure they are always available to be
    //    removed. Also don't call removed clients or add them back.

    // Handle case (1) by saving a list of clients to notify. A separate list also ensure
    // a client is either in m_clients or m_clientsAwaitingCallback.
    Vector<ResourceClient*> clientsToNotify;
    copyToVector(m_clientsAwaitingCallback, clientsToNotify);

    for (size_t i = 0; i < clientsToNotify.size(); ++i) {
        ResourceClient* client = clientsToNotify[i];

        // Handle case (2) to skip removed clients.
        if (!m_clientsAwaitingCallback.remove(client))
            continue;
        m_clients.add(client);
        didAddClient(client);
    }

    // It is still possible for the above loop to finish a new client synchronously.
    // If there's no client waiting we should deschedule.
    bool scheduled = ResourceCallback::callbackHandler()->isScheduled(this);
    if (scheduled && m_clientsAwaitingCallback.isEmpty())
        ResourceCallback::callbackHandler()->cancel(this);

    // Prevent the case when there are clients waiting but no callback scheduled.
    ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled);
}

void Resource::prune()
{
    destroyDecodedDataIfPossible();
    unlock();
}

void Resource::setResourceToRevalidate(Resource* resource)
{
    ASSERT(resource);
    ASSERT(!m_resourceToRevalidate);
    ASSERT(resource != this);
    ASSERT(m_handlesToRevalidate.isEmpty());
    ASSERT(resource->type() == type());

    WTF_LOG(ResourceLoading, "Resource %p setResourceToRevalidate %p", this, resource);

    // The following assert should be investigated whenever it occurs. Although it should never fire, it currently does in rare circumstances.
    // https://bugs.webkit.org/show_bug.cgi?id=28604.
    // So the code needs to be robust to this assert failing thus the "if (m_resourceToRevalidate->m_proxyResource == this)" in Resource::clearResourceToRevalidate.
    ASSERT(!resource->m_proxyResource);

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

void Resource::clearResourceToRevalidate()
{
    ASSERT(m_resourceToRevalidate);
    if (m_switchingClientsToRevalidatedResource)
        return;

    // A resource may start revalidation before this method has been called, so check that this resource is still the proxy resource before clearing it out.
    if (m_resourceToRevalidate->m_proxyResource == this) {
        m_resourceToRevalidate->m_proxyResource = nullptr;
        m_resourceToRevalidate->deleteIfPossible();
    }
    m_handlesToRevalidate.clear();
    m_resourceToRevalidate = nullptr;
    deleteIfPossible();
}

void Resource::switchClientsToRevalidatedResource()
{
    ASSERT(m_resourceToRevalidate);
    ASSERT(memoryCache()->contains(m_resourceToRevalidate));
    ASSERT(!memoryCache()->contains(this));

    WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate.get());

    m_resourceToRevalidate->m_identifier = m_identifier;

    m_switchingClientsToRevalidatedResource = true;
    HashSet<ResourcePtrBase*>::iterator end = m_handlesToRevalidate.end();
    for (HashSet<ResourcePtrBase*>::iterator it = m_handlesToRevalidate.begin(); it != end; ++it) {
        ResourcePtrBase* handle = *it;
        handle->m_resource = m_resourceToRevalidate;
        m_resourceToRevalidate->registerHandle(handle);
        --m_handleCount;
    }
    ASSERT(!m_handleCount);
    m_handlesToRevalidate.clear();

    Vector<ResourceClient*> clientsToMove;
    HashCountedSet<ResourceClient*>::iterator end2 = m_clients.end();
    for (HashCountedSet<ResourceClient*>::iterator it = m_clients.begin(); it != end2; ++it) {
        ResourceClient* client = it->key;
        unsigned count = it->value;
        while (count) {
            clientsToMove.append(client);
            --count;
        }
    }

    unsigned moveCount = clientsToMove.size();
    for (unsigned n = 0; n < moveCount; ++n)
        removeClient(clientsToMove[n]);
    ASSERT(m_clients.isEmpty());

    for (unsigned n = 0; n < moveCount; ++n)
        m_resourceToRevalidate->addClientToSet(clientsToMove[n]);
    for (unsigned n = 0; n < moveCount; ++n) {
        // 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(clientsToMove[n]))
            m_resourceToRevalidate->didAddClient(clientsToMove[n]);
    }
    m_switchingClientsToRevalidatedResource = false;
}

void Resource::updateResponseAfterRevalidation(const ResourceResponse& validatingResponse)
{
    m_responseTimestamp = currentTime();

    // RFC2616 10.3.5
    // Update cached headers from the 304 response
    const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields();
    HTTPHeaderMap::const_iterator end = newHeaders.end();
    for (HTTPHeaderMap::const_iterator it = newHeaders.begin(); it != end; ++it) {
        // Entity headers should not be sent by servers when generating a 304
        // response; misconfigured servers send them anyway. We shouldn't allow
        // such headers to update the original request. We'll base this on the
        // list defined by RFC2616 7.1, with a few additions for extension headers
        // we care about.
        if (!shouldUpdateHeaderAfterRevalidation(it->key))
            continue;
        m_response.setHTTPHeaderField(it->key, it->value);
    }
}

void Resource::revalidationSucceeded(const ResourceResponse& response)
{
    ASSERT(m_resourceToRevalidate);
    ASSERT(!memoryCache()->contains(m_resourceToRevalidate));
    ASSERT(m_resourceToRevalidate->isLoaded());

    // Calling evict() can potentially delete revalidatingResource, which we use
    // below. This mustn't be the case since revalidation means it is loaded
    // and so canDelete() is false.
    ASSERT(!canDelete());

    m_resourceToRevalidate->updateResponseAfterRevalidation(response);
    memoryCache()->replace(m_resourceToRevalidate, this);

    switchClientsToRevalidatedResource();
    assertAlive();
    // clearResourceToRevalidate deletes this.
    clearResourceToRevalidate();
}

void Resource::revalidationFailed()
{
    ASSERT(WTF::isMainThread());
    WTF_LOG(ResourceLoading, "Revalidation failed for %p", this);
    ASSERT(resourceToRevalidate());
    clearResourceToRevalidate();
}

void Resource::registerHandle(ResourcePtrBase* h)
{
    assertAlive();
    ++m_handleCount;
    if (m_resourceToRevalidate)
        m_handlesToRevalidate.add(h);
}

void Resource::unregisterHandle(ResourcePtrBase* h)
{
    assertAlive();
    ASSERT(m_handleCount > 0);
    --m_handleCount;

    if (m_resourceToRevalidate)
        m_handlesToRevalidate.remove(h);

    if (!m_handleCount) {
        if (deleteIfPossible())
            return;
        unlock();
    } else if (m_handleCount == 1 && memoryCache()->contains(this)) {
        unlock();
        if (!hasClients())
            memoryCache()->prune(this);
    }
}

bool Resource::hasCacheControlNoStoreHeader()
{
    return m_response.cacheControlContainsNoStore() || m_resourceRequest.cacheControlContainsNoStore();
}

bool Resource::mustRevalidateDueToCacheHeaders()
{
    return !canUseResponse(m_response, m_responseTimestamp) || m_resourceRequest.cacheControlContainsNoCache() || m_resourceRequest.cacheControlContainsNoStore();
}

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

    if (hasCacheControlNoStoreHeader())
        return false;
    return m_response.hasCacheValidatorFields() || m_resourceRequest.hasCacheValidatorFields();
}

bool Resource::isPurgeable() const
{
    return m_data && !m_data->isLocked();
}

bool Resource::wasPurged() const
{
    return m_wasPurged;
}

bool Resource::lock()
{
    if (!m_data)
        return true;
    if (m_data->isLocked())
        return true;

    ASSERT(!hasClients());

    if (!m_data->lock()) {
        m_wasPurged = true;
        return false;
    }
    return true;
}

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

void Resource::didChangePriority(ResourceLoadPriority loadPriority, int intraPriorityValue)
{
    if (m_loader)
        m_loader->didChangePriority(loadPriority, intraPriorityValue);
}

Resource::ResourceCallback* Resource::ResourceCallback::callbackHandler()
{
    DEFINE_STATIC_LOCAL(ResourceCallback, callbackHandler, ());
    return &callbackHandler;
}

Resource::ResourceCallback::ResourceCallback()
    : m_callbackTimer(this, &ResourceCallback::timerFired)
{
}

void Resource::ResourceCallback::schedule(Resource* resource)
{
    if (!m_callbackTimer.isActive())
        m_callbackTimer.startOneShot(0, FROM_HERE);
    resource->assertAlive();
    m_resourcesWithPendingClients.add(resource);
}

void Resource::ResourceCallback::cancel(Resource* resource)
{
    resource->assertAlive();
    m_resourcesWithPendingClients.remove(resource);
    if (m_callbackTimer.isActive() && m_resourcesWithPendingClients.isEmpty())
        m_callbackTimer.stop();
}

bool Resource::ResourceCallback::isScheduled(Resource* resource) const
{
    return m_resourcesWithPendingClients.contains(resource);
}

void Resource::ResourceCallback::timerFired(Timer<ResourceCallback>*)
{
    HashSet<Resource*>::iterator end = m_resourcesWithPendingClients.end();
    Vector<ResourcePtr<Resource> > resources;
    for (HashSet<Resource*>::iterator it = m_resourcesWithPendingClients.begin(); it != end; ++it)
        resources.append(*it);
    m_resourcesWithPendingClients.clear();

    for (size_t i = 0; i < resources.size(); i++) {
        resources[i]->assertAlive();
        resources[i]->finishPendingClients();
        resources[i]->assertAlive();
    }

    for (size_t i = 0; i < resources.size(); i++)
        resources[i]->assertAlive();
}

static const char* initatorTypeNameToString(const AtomicString& initiatorTypeName)
{
    if (initiatorTypeName == FetchInitiatorTypeNames::css)
        return "CSS resource";
    if (initiatorTypeName == FetchInitiatorTypeNames::document)
        return "Document";
    if (initiatorTypeName == FetchInitiatorTypeNames::icon)
        return "Icon";
    if (initiatorTypeName == FetchInitiatorTypeNames::internal)
        return "Internal resource";
    if (initiatorTypeName == FetchInitiatorTypeNames::link)
        return "Link element resource";
    if (initiatorTypeName == FetchInitiatorTypeNames::processinginstruction)
        return "Processing instruction";
    if (initiatorTypeName == FetchInitiatorTypeNames::xml)
        return "XML resource";
    return "Resource";
}

const char* Resource::resourceTypeToString(Type type, const FetchInitiatorInfo& initiatorInfo)
{
    switch (type) {
    case Resource::MainResource:
        return "Main resource";
    case Resource::Image:
        return "Image";
    case Resource::Font:
        return "Font";
    case Resource::Raw:
        return initatorTypeNameToString(initiatorInfo.name);
    case Resource::LinkPrefetch:
        return "Link prefetch resource";
    case Resource::LinkSubresource:
        return "Link subresource";
    case Resource::ImportResource:
        return "Imported resource";
    case Resource::Media:
        return "Media";
    }
    ASSERT_NOT_REACHED();
    return initatorTypeNameToString(initiatorInfo.name);
}

#if !LOG_DISABLED
const char* ResourceTypeName(Resource::Type type)
{
    switch (type) {
    case Resource::MainResource:
        return "MainResource";
    case Resource::Image:
        return "Image";
    case Resource::Font:
        return "Font";
    case Resource::Raw:
        return "Raw";
    case Resource::LinkPrefetch:
        return "LinkPrefetch";
    case Resource::LinkSubresource:
        return "LinkSubresource";
    case Resource::ImportResource:
        return "ImportResource";
    case Resource::Media:
        return "Media";
    }
    ASSERT_NOT_REACHED();
    return "Unknown";
}
#endif // !LOG_DISABLED

}
