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

📄 docloader.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) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.    Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/    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.    This class provides all functionality needed for loading images, style sheets and html    pages from the web. It has a memory cache for these objects.*/#include "config.h"#include "DocLoader.h"#include "Cache.h"#include "CachedCSSStyleSheet.h"#include "CachedFont.h"#include "CachedImage.h"#include "CachedScript.h"#include "CachedXSLStyleSheet.h"#include "Console.h"#include "CString.h"#include "Document.h"#include "DOMWindow.h"#include "Frame.h"#include "FrameLoader.h"#include "loader.h"#include "SecurityOrigin.h"#include "Settings.h"#define PRELOAD_DEBUG 0namespace WebCore {DocLoader::DocLoader(Document* doc)    : m_cache(cache())    , m_doc(doc)    , m_requestCount(0)    , m_autoLoadImages(true)    , m_loadInProgress(false)    , m_allowStaleResources(false){    m_cache->addDocLoader(this);}DocLoader::~DocLoader(){    clearPreloads();    DocumentResourceMap::iterator end = m_documentResources.end();    for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it)        it->second->setDocLoader(0);    m_cache->removeDocLoader(this);    // Make sure no requests still point to this DocLoader    ASSERT(m_requestCount == 0);}Frame* DocLoader::frame() const{    return m_doc->frame();}void DocLoader::checkForReload(const KURL& fullURL){    if (m_allowStaleResources)        return; // Don't reload resources while pasting    if (fullURL.isEmpty())        return;        if (m_reloadedURLs.contains(fullURL.string()))        return;        CachedResource* existing = cache()->resourceForURL(fullURL.string());    if (!existing || existing->isPreloaded())        return;    switch (cachePolicy()) {    case CachePolicyVerify:        if (!existing->mustRevalidate(CachePolicyVerify))            return;        cache()->revalidateResource(existing, this);        break;    case CachePolicyCache:        if (!existing->mustRevalidate(CachePolicyCache))            return;        cache()->revalidateResource(existing, this);        break;    case CachePolicyReload:        cache()->remove(existing);                break;    case CachePolicyRevalidate:        cache()->revalidateResource(existing, this);        break;    default:        ASSERT_NOT_REACHED();    }    m_reloadedURLs.add(fullURL.string());}CachedImage* DocLoader::requestImage(const String& url){    CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url, String()));    if (autoLoadImages() && resource && resource->stillNeedsLoad()) {        resource->setLoading(true);        cache()->loader()->load(this, resource, true);    }    return resource;}CachedFont* DocLoader::requestFont(const String& url){    return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, url, String()));}CachedCSSStyleSheet* DocLoader::requestCSSStyleSheet(const String& url, const String& charset){    return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset));}CachedCSSStyleSheet* DocLoader::requestUserCSSStyleSheet(const String& url, const String& charset){    return cache()->requestUserCSSStyleSheet(this, url, charset);}CachedScript* DocLoader::requestScript(const String& url, const String& charset){    return static_cast<CachedScript*>(requestResource(CachedResource::Script, url, charset));}#if ENABLE(XSLT)CachedXSLStyleSheet* DocLoader::requestXSLStyleSheet(const String& url){    return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XSLStyleSheet, url, String()));}#endif#if ENABLE(XBL)CachedXBLDocument* DocLoader::requestXBLDocument(const String& url){    return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XBL, url, String()));}#endifbool DocLoader::canRequest(CachedResource::Type type, const KURL& url){    // Some types of resources can be loaded only from the same origin.  Other    // types of resources, like Images, Scripts, and CSS, can be loaded from    // any URL.    switch (type) {    case CachedResource::ImageResource:    case CachedResource::CSSStyleSheet:    case CachedResource::Script:    case CachedResource::FontResource:        // These types of resources can be loaded from any origin.        // FIXME: Are we sure about CachedResource::FontResource?        break;#if ENABLE(XSLT)    case CachedResource::XSLStyleSheet:#endif#if ENABLE(XBL)    case CachedResource::XBL:#endif#if ENABLE(XSLT) || ENABLE(XBL)        if (!m_doc->securityOrigin()->canRequest(url)) {            printAccessDeniedMessage(url);            return false;        }        break;#endif    default:        ASSERT_NOT_REACHED();        break;    }    return true;}CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, bool isPreload){    KURL fullURL = m_doc->completeURL(url);    if (!fullURL.isValid() || !canRequest(type, fullURL))        return 0;    if (cache()->disabled()) {        DocumentResourceMap::iterator it = m_documentResources.find(fullURL.string());                if (it != m_documentResources.end()) {            it->second->setDocLoader(0);            m_documentResources.remove(it);        }    }    checkForReload(fullURL);    CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, isPreload);    if (resource) {        // Check final URL of resource to catch redirects.        // See <https://bugs.webkit.org/show_bug.cgi?id=21963>.        if (!canRequest(type, KURL(resource->url())))            return 0;        m_documentResources.set(resource->url(), resource);        checkCacheObjectStatus(resource);    }    return resource;}void DocLoader::printAccessDeniedMessage(const KURL& url) const{    if (url.isNull())        return;    if (!frame())        return;    Settings* settings = frame()->settings();    if (!settings || settings->privateBrowsingEnabled())        return;    String message = m_doc->url().isNull() ?        String::format("Unsafe attempt to load URL %s.",                       url.string().utf8().data()) :        String::format("Unsafe attempt to load URL %s from frame with URL %s. "                       "Domains, protocols and ports must match.\n",                       url.string().utf8().data(),                       m_doc->url().string().utf8().data());    // FIXME: provide a real line number and source URL.    frame()->domWindow()->console()->addMessage(OtherMessageSource, ErrorMessageLevel, message, 1, String());}void DocLoader::setAutoLoadImages(bool enable){    if (enable == m_autoLoadImages)        return;    m_autoLoadImages = enable;    if (!m_autoLoadImages)        return;    DocumentResourceMap::iterator end = m_documentResources.end();    for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) {        CachedResource* resource = it->second.get();        if (resource->type() == CachedResource::ImageResource) {            CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource));            if (image->stillNeedsLoad())                cache()->loader()->load(this, image, true);        }    }}CachePolicy DocLoader::cachePolicy() const{    return frame() ? frame()->loader()->cachePolicy() : CachePolicyVerify;}void DocLoader::removeCachedResource(CachedResource* resource) const{    m_documentResources.remove(resource->url());}void DocLoader::setLoadInProgress(bool load){    m_loadInProgress = load;    if (!load && frame())        frame()->loader()->loadDone();}void DocLoader::checkCacheObjectStatus(CachedResource* resource){    // Return from the function for objects that we didn't load from the cache or if we don't have a frame.    if (!resource || !frame())        return;    switch (resource->status()) {        case CachedResource::Cached:            break;        case CachedResource::NotCached:        case CachedResource::Unknown:        case CachedResource::New:        case CachedResource::Pending:            return;    }    // FIXME: If the WebKit client changes or cancels the request, WebCore does not respect this and continues the load.    frame()->loader()->loadedResourceFromMemoryCache(resource);}void DocLoader::incrementRequestCount(){    ++m_requestCount;}void DocLoader::decrementRequestCount(){    --m_requestCount;    ASSERT(m_requestCount > -1);}int DocLoader::requestCount(){    if (loadInProgress())         return m_requestCount + 1;    return m_requestCount;}    void DocLoader::preload(CachedResource::Type type, const String& url, const String& charset, bool referencedFromBody){    bool hasRendering = m_doc->body() && m_doc->body()->renderer();    if (!hasRendering && (referencedFromBody || type == CachedResource::ImageResource)) {        // Don't preload images or body resources before we have something to draw. This prevents        // preloads from body delaying first display when bandwidth is limited.        PendingPreload pendingPreload = { type, url, charset };        m_pendingPreloads.append(pendingPreload);        return;    }    requestPreload(type, url, charset);}void DocLoader::checkForPendingPreloads() {    unsigned count = m_pendingPreloads.size();    if (!count || !m_doc->body() || !m_doc->body()->renderer())        return;    for (unsigned i = 0; i < count; ++i) {        PendingPreload& preload = m_pendingPreloads[i];        requestPreload(preload.m_type, preload.m_url, preload.m_charset);    }    m_pendingPreloads.clear();}void DocLoader::requestPreload(CachedResource::Type type, const String& url, const String& charset){    String encoding;    if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet)        encoding = charset.isEmpty() ? m_doc->frame()->loader()->encoding() : charset;    CachedResource* resource = requestResource(type, url, encoding, true);    if (!resource || m_preloads.contains(resource))        return;    resource->increasePreloadCount();    m_preloads.add(resource);#if PRELOAD_DEBUG    printf("PRELOADING %s\n",  resource->url().latin1().data());#endif}void DocLoader::clearPreloads(){#if PRELOAD_DEBUG    printPreloadStats();#endif    ListHashSet<CachedResource*>::iterator end = m_preloads.end();    for (ListHashSet<CachedResource*>::iterator it = m_preloads.begin(); it != end; ++it) {        CachedResource* res = *it;        res->decreasePreloadCount();        if (res->canDelete() && !res->inCache())            delete res;        else if (res->preloadResult() == CachedResource::PreloadNotReferenced)            cache()->remove(res);    }    m_preloads.clear();}void DocLoader::clearPendingPreloads(){    m_pendingPreloads.clear();}#if PRELOAD_DEBUGvoid DocLoader::printPreloadStats(){    unsigned scripts = 0;    unsigned scriptMisses = 0;    unsigned stylesheets = 0;    unsigned stylesheetMisses = 0;    unsigned images = 0;    unsigned imageMisses = 0;    ListHashSet<CachedResource*>::iterator end = m_preloads.end();    for (ListHashSet<CachedResource*>::iterator it = m_preloads.begin(); it != end; ++it) {        CachedResource* res = *it;        if (res->preloadResult() == CachedResource::PreloadNotReferenced)            printf("!! UNREFERENCED PRELOAD %s\n", res->url().latin1().data());        else if (res->preloadResult() == CachedResource::PreloadReferencedWhileComplete)            printf("HIT COMPLETE PRELOAD %s\n", res->url().latin1().data());        else if (res->preloadResult() == CachedResource::PreloadReferencedWhileLoading)            printf("HIT LOADING PRELOAD %s\n", res->url().latin1().data());                if (res->type() == CachedResource::Script) {            scripts++;            if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading)                scriptMisses++;        } else if (res->type() == CachedResource::CSSStyleSheet) {            stylesheets++;            if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading)                stylesheetMisses++;        } else {            images++;            if (res->preloadResult() < CachedResource::PreloadReferencedWhileLoading)                imageMisses++;        }                if (res->errorOccurred())            cache()->remove(res);                res->decreasePreloadCount();    }    m_preloads.clear();        if (scripts)        printf("SCRIPTS: %d (%d hits, hit rate %d%%)\n", scripts, scripts - scriptMisses, (scripts - scriptMisses) * 100 / scripts);    if (stylesheets)        printf("STYLESHEETS: %d (%d hits, hit rate %d%%)\n", stylesheets, stylesheets - stylesheetMisses, (stylesheets - stylesheetMisses) * 100 / stylesheets);    if (images)        printf("IMAGES:  %d (%d hits, hit rate %d%%)\n", images, images - imageMisses, (images - imageMisses) * 100 / images);}#endif    }

⌨️ 快捷键说明

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