blob: bae9d9346279bdf7081a54848368d509d63aac57 [file] [log] [blame]
/*
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 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "CachedResource.h"
#include "Cache.h"
#include "DocLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "KURL.h"
#include "Request.h"
#include "SystemTime.h"
#include <wtf/Vector.h>
namespace WebCore {
CachedResource::CachedResource(const String& URL, Type type, bool forCache, bool sendResourceLoadCallbacks)
: m_lastDecodedAccessTime(0)
, m_sendResourceLoadCallbacks(sendResourceLoadCallbacks)
, m_inCache(forCache)
, m_docLoader(0)
{
m_url = URL;
m_type = type;
m_status = Pending;
m_encodedSize = 0;
m_decodedSize = 0;
m_request = 0;
m_accessCount = 0;
m_inLiveDecodedResourcesList = false;
m_nextInAllResourcesList = 0;
m_prevInAllResourcesList = 0;
m_nextInLiveResourcesList = 0;
m_prevInLiveResourcesList = 0;
#ifndef NDEBUG
m_deleted = false;
m_lruIndex = 0;
#endif
m_errorOccurred = false;
m_shouldTreatAsLocal = FrameLoader::shouldTreatURLAsLocal(m_url);
}
CachedResource::~CachedResource()
{
ASSERT(!inCache());
ASSERT(!m_deleted);
#ifndef NDEBUG
m_deleted = true;
#endif
if (m_docLoader)
m_docLoader->removeCachedResource(this);
}
void CachedResource::finish()
{
m_status = Cached;
}
bool CachedResource::isExpired() const
{
if (!m_response.expirationDate())
return false;
time_t now = time(0);
return (difftime(now, m_response.expirationDate()) >= 0);
}
void CachedResource::setRequest(Request* request)
{
if (request && !m_request)
m_status = Pending;
m_request = request;
if (canDelete() && !inCache())
delete this;
}
void CachedResource::ref(CachedResourceClient *c)
{
if (!referenced() && inCache())
cache()->addToLiveResourcesSize(this);
m_clients.add(c);
}
void CachedResource::deref(CachedResourceClient *c)
{
ASSERT(m_clients.contains(c));
m_clients.remove(c);
if (canDelete() && !inCache())
delete this;
else if (!referenced() && inCache()) {
cache()->removeFromLiveResourcesSize(this);
cache()->removeFromLiveDecodedResourcesList(this);
allReferencesRemoved();
cache()->pruneDeadResources();
}
}
void CachedResource::setDecodedSize(unsigned size)
{
if (size == m_decodedSize)
return;
int delta = size - m_decodedSize;
// The object must now be moved to a different queue, since its size has been changed.
// We have to remove explicitly before updating m_decodedSize, so that we find the correct previous
// queue.
if (inCache())
cache()->removeFromLRUList(this);
m_decodedSize = size;
if (inCache()) {
// Now insert into the new LRU list.
cache()->insertInLRUList(this);
// Insert into or remove from the live decoded list if necessary.
if (m_decodedSize && !m_inLiveDecodedResourcesList && referenced())
cache()->insertInLiveDecodedResourcesList(this);
else if (!m_decodedSize && m_inLiveDecodedResourcesList)
cache()->removeFromLiveDecodedResourcesList(this);
// Update the cache's size totals.
cache()->adjustSize(referenced(), delta, delta);
}
}
void CachedResource::setEncodedSize(unsigned size)
{
if (size == m_encodedSize)
return;
// The size cannot ever shrink (unless it is being nulled out because of an error). If it ever does, assert.
ASSERT(size == 0 || size >= m_encodedSize);
int delta = size - m_encodedSize;
// The object must now be moved to a different queue, since its size has been changed.
// We have to remove explicitly before updating m_encodedSize, so that we find the correct previous
// queue.
if (inCache())
cache()->removeFromLRUList(this);
m_encodedSize = size;
if (inCache()) {
// Now insert into the new LRU list.
cache()->insertInLRUList(this);
// Update the cache's size totals.
cache()->adjustSize(referenced(), delta, 0);
}
}
void CachedResource::didAccessDecodedData(double timeStamp)
{
m_lastDecodedAccessTime = timeStamp;
if (inCache()) {
if (m_inLiveDecodedResourcesList) {
cache()->removeFromLiveDecodedResourcesList(this);
cache()->insertInLiveDecodedResourcesList(this);
}
cache()->pruneLiveResources();
}
}
}