⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cachedresource.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
字号:
/*    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 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 "Cache.h"#include "CachedResourceHandle.h"#include "DocLoader.h"#include "Frame.h"#include "FrameLoader.h"#include "KURL.h"#include "PurgeableBuffer.h"#include "Request.h"#include <wtf/RefCountedLeakCounter.h>#include <wtf/Vector.h>using namespace WTF;namespace WebCore {#ifndef NDEBUGstatic RefCountedLeakCounter cachedResourceLeakCounter("CachedResource");#endifCachedResource::CachedResource(const String& url, Type type)    : m_url(url)    , m_lastDecodedAccessTime(0)    , m_sendResourceLoadCallbacks(true)    , m_preloadCount(0)    , m_preloadResult(PreloadNotReferenced)    , m_requestedFromNetworkingLayer(false)    , m_inCache(false)    , m_loading(false)    , m_docLoader(0)    , m_handleCount(0)    , m_resourceToRevalidate(0)    , m_isBeingRevalidated(false)    , m_expirationDate(0){#ifndef NDEBUG    cachedResourceLeakCounter.increment();#endif    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;}CachedResource::~CachedResource(){    ASSERT(!inCache());    ASSERT(!m_deleted);    ASSERT(url().isNull() || cache()->resourceForURL(url()) != this);#ifndef NDEBUG    m_deleted = true;    cachedResourceLeakCounter.decrement();#endif    if (m_resourceToRevalidate)        m_resourceToRevalidate->m_isBeingRevalidated = false;    if (m_docLoader)        m_docLoader->removeCachedResource(this);}    void CachedResource::load(DocLoader* docLoader, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks){    m_sendResourceLoadCallbacks = sendResourceLoadCallbacks;    cache()->loader()->load(docLoader, this, incremental, skipCanLoadCheck, sendResourceLoadCallbacks);    m_loading = true;}void CachedResource::finish(){    m_status = Cached;}bool CachedResource::isExpired() const{    if (!m_expirationDate)        return false;    time_t now = time(0);    return difftime(now, m_expirationDate) >= 0;}void CachedResource::setResponse(const ResourceResponse& response){    m_response = response;    m_expirationDate = response.expirationDate();}void CachedResource::setRequest(Request* request){    if (request && !m_request)        m_status = Pending;    m_request = request;    if (canDelete() && !inCache())        delete this;}void CachedResource::addClient(CachedResourceClient *c){    ASSERT(!isPurgeable());    if (m_preloadResult == PreloadNotReferenced) {        if (isLoaded())            m_preloadResult = PreloadReferencedWhileComplete;        else if (m_requestedFromNetworkingLayer)            m_preloadResult = PreloadReferencedWhileLoading;        else            m_preloadResult = PreloadReferenced;    }    if (!hasClients() && inCache())        cache()->addToLiveResourcesSize(this);    m_clients.add(c);}void CachedResource::removeClient(CachedResourceClient *c){    ASSERT(m_clients.contains(c));    m_clients.remove(c);    if (canDelete() && !inCache())        delete this;    else if (!hasClients() && inCache()) {        cache()->removeFromLiveResourcesSize(this);        cache()->removeFromLiveDecodedResourcesList(this);        allClientsRemoved();        cache()->prune();    }}void CachedResource::deleteIfPossible(){    if (canDelete() && !inCache())        delete this;}    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 && hasClients())            cache()->insertInLiveDecodedResourcesList(this);        else if (!m_decodedSize && m_inLiveDecodedResourcesList)            cache()->removeFromLiveDecodedResourcesList(this);        // Update the cache's size totals.        cache()->adjustSize(hasClients(), 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(hasClients(), delta);    }}void CachedResource::didAccessDecodedData(double timeStamp){    m_lastDecodedAccessTime = timeStamp;        if (inCache()) {        if (m_inLiveDecodedResourcesList) {            cache()->removeFromLiveDecodedResourcesList(this);            cache()->insertInLiveDecodedResourcesList(this);        }        cache()->prune();    }}    void CachedResource::setResourceToRevalidate(CachedResource* resource) {     ASSERT(resource);    ASSERT(!m_resourceToRevalidate);    ASSERT(resource != this);    ASSERT(!resource->m_isBeingRevalidated);    ASSERT(m_handlesToRevalidate.isEmpty());    ASSERT(resource->type() == type());    resource->m_isBeingRevalidated = true;    m_resourceToRevalidate = resource;}void CachedResource::clearResourceToRevalidate() {     ASSERT(m_resourceToRevalidate);    ASSERT(m_resourceToRevalidate->m_isBeingRevalidated);    m_resourceToRevalidate->m_isBeingRevalidated = false;    m_resourceToRevalidate->deleteIfPossible();    m_handlesToRevalidate.clear();    m_resourceToRevalidate = 0;    deleteIfPossible();}    void CachedResource::switchClientsToRevalidatedResource(){    ASSERT(m_resourceToRevalidate);    ASSERT(!inCache());    HashSet<CachedResourceHandleBase*>::iterator end = m_handlesToRevalidate.end();    for (HashSet<CachedResourceHandleBase*>::iterator it = m_handlesToRevalidate.begin(); it != end; ++it) {        CachedResourceHandleBase* handle = *it;        handle->m_resource = m_resourceToRevalidate;        m_resourceToRevalidate->registerHandle(handle);        --m_handleCount;    }    ASSERT(!m_handleCount);    m_handlesToRevalidate.clear();    Vector<CachedResourceClient*> clientsToMove;    HashCountedSet<CachedResourceClient*>::iterator end2 = m_clients.end();    for (HashCountedSet<CachedResourceClient*>::iterator it = m_clients.begin(); it != end2; ++it) {        CachedResourceClient* client = it->first;        unsigned count = it->second;        while (count) {            clientsToMove.append(client);            --count;        }    }    // Equivalent of calling removeClient() for all clients    m_clients.clear();        unsigned moveCount = clientsToMove.size();    for (unsigned n = 0; n < moveCount; ++n)        m_resourceToRevalidate->addClient(clientsToMove[n]);}    bool CachedResource::canUseCacheValidator() const{    return !m_loading && (!m_response.httpHeaderField("Last-Modified").isEmpty() || !m_response.httpHeaderField("ETag").isEmpty());}    bool CachedResource::mustRevalidate(CachePolicy cachePolicy) const{    if (m_loading)        return false;    // FIXME: Also look at max-age, min-fresh, max-stale in Cache-Control    if (cachePolicy == CachePolicyCache)        return m_response.cacheControlContainsNoCache() || (isExpired() && m_response.cacheControlContainsMustRevalidate());    return isExpired() || m_response.cacheControlContainsNoCache();}bool CachedResource::isSafeToMakePurgeable() const{     return !hasClients() && !m_isBeingRevalidated && !m_resourceToRevalidate; }bool CachedResource::makePurgeable(bool purgeable) {     if (purgeable) {        ASSERT(isSafeToMakePurgeable());        if (m_purgeableData) {            ASSERT(!m_data);            return true;        }        if (!m_data)            return false;                // Should not make buffer purgeable if it has refs othen than this since we don't want two copies.        if (!m_data->hasOneRef())            return false;                // Purgeable buffers are allocated in multiples of the page size (4KB in common CPUs) so it does not make sense for very small buffers.        const size_t purgeableThreshold = 4 * 4096;        if (m_data->size() < purgeableThreshold)            return false;                if (m_data->hasPurgeableBuffer()) {            m_purgeableData.set(m_data->releasePurgeableBuffer());        } else {            m_purgeableData.set(PurgeableBuffer::create(m_data->data(), m_data->size()));            if (!m_purgeableData)                return false;        }                m_purgeableData->makePurgeable(true);        m_data.clear();        return true;    }    if (!m_purgeableData)        return true;    ASSERT(!m_data);    ASSERT(!hasClients());    if (!m_purgeableData->makePurgeable(false))        return false;     m_data = SharedBuffer::adoptPurgeableBuffer(m_purgeableData.release());    return true;}bool CachedResource::isPurgeable() const{    return m_purgeableData && m_purgeableData->isPurgeable();}bool CachedResource::wasPurged() const{    return m_purgeableData && m_purgeableData->wasPurged();}unsigned CachedResource::overheadSize() const{    return sizeof(CachedResource) + m_response.memoryUsage() + 576;    /*        576 = 192 +                   // average size of m_url              384;                    // average size of m_clients hash map    */}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -