diff options
author | Iain Merrick <husky@google.com> | 2010-09-13 16:35:48 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-09-16 12:10:42 +0100 |
commit | 5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306 (patch) | |
tree | ddce1aa5e3b6967a69691892e500897558ff8ab6 /WebCore/loader/DocLoader.cpp | |
parent | 12bec63ec71e46baba27f0bd9bd9d8067683690a (diff) | |
download | external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.zip external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.gz external_webkit-5abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306.tar.bz2 |
Merge WebKit at r67178 : Initial merge by git.
Change-Id: I57e01163b6866cb029cdadf405a0394a3918bc18
Diffstat (limited to 'WebCore/loader/DocLoader.cpp')
-rw-r--r-- | WebCore/loader/DocLoader.cpp | 559 |
1 files changed, 0 insertions, 559 deletions
diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp deleted file mode 100644 index d04e148..0000000 --- a/WebCore/loader/DocLoader.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - 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 "loader.h" -#include "Cache.h" -#include "CachedCSSStyleSheet.h" -#include "CachedFont.h" -#include "CachedImage.h" -#include "CachedScript.h" -#include "CachedXSLStyleSheet.h" -#include "Console.h" -#include "Document.h" -#include "DOMWindow.h" -#include "HTMLElement.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "PingLoader.h" -#include "SecurityOrigin.h" -#include "Settings.h" -#include <wtf/text/CString.h> - -#define PRELOAD_DEBUG 0 - -namespace WebCore { - -DocLoader::DocLoader(Document* doc) - : m_cache(cache()) - , m_doc(doc) - , m_requestCount(0) -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - , m_blockNetworkImage(false) -#endif - , m_autoLoadImages(true) - , m_loadInProgress(false) - , m_allowStaleResources(false) -{ - m_cache->addDocLoader(this); -} - -DocLoader::~DocLoader() -{ - if (m_requestCount) - m_cache->loader()->cancelRequests(this); - - 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; - case CachePolicyAllowStale: - return; - } - - m_reloadedURLs.add(fullURL.string()); -} - -CachedImage* DocLoader::requestImage(const String& url) -{ - if (Frame* f = frame()) { - Settings* settings = f->settings(); - if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) - return 0; - - if (f->loader()->pageDismissalEventBeingDispatched()) { - KURL completeURL = m_doc->completeURL(url); - if (completeURL.isValid() && canRequest(CachedResource::ImageResource, completeURL)) - PingLoader::loadImage(f, completeURL); - return 0; - } - } - CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url, String())); - if (autoLoadImages() && resource && resource->stillNeedsLoad()) { -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (shouldBlockNetworkImage(url)) { - return resource; - } -#endif - 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(LINK_PREFETCH) -CachedResource* DocLoader::requestLinkPrefetch(const String& url) -{ - ASSERT(frame()); - return requestResource(CachedResource::LinkPrefetch, url, String()); -} -#endif - -bool 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: -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: -#endif - // These types of resources can be loaded from any origin. - // FIXME: Are we sure about CachedResource::FontResource? - break; -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: - if (!m_doc->securityOrigin()->canRequest(url)) { - printAccessDeniedMessage(url); - return false; - } - break; -#endif - default: - ASSERT_NOT_REACHED(); - break; - } - - // Given that the load is allowed by the same-origin policy, we should - // check whether the load passes the mixed-content policy. - // - // Note: Currently, we always allow mixed content, but we generate a - // callback to the FrameLoaderClient in case the embedder wants to - // update any security indicators. - // - switch (type) { - case CachedResource::Script: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif - // These resource can inject script into the current document. - if (Frame* f = frame()) - f->loader()->checkIfRunInsecureContent(m_doc->securityOrigin(), url); - break; - case CachedResource::ImageResource: - case CachedResource::CSSStyleSheet: - case CachedResource::FontResource: { - // These resources can corrupt only the frame's pixels. - if (Frame* f = frame()) { - Frame* top = f->tree()->top(); - top->loader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), url); - } - break; - } -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: - // Prefetch cannot affect the current document. - break; -#endif - default: - ASSERT_NOT_REACHED(); - break; - } - // FIXME: Consider letting the embedder block mixed content loads. - 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 (fullURL != resource->url() && !canRequest(type, KURL(ParsedURLString, 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, LogMessageType, 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)); -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (shouldBlockNetworkImage(image->url())) - continue; -#endif - - if (image->stillNeedsLoad()) - cache()->loader()->load(this, image, true); - } - } -} - -#ifdef ANDROID_BLOCK_NETWORK_IMAGE -bool DocLoader::shouldBlockNetworkImage(const String& url) const -{ - if (!m_blockNetworkImage) - return false; - - KURL kurl = m_doc->completeURL(url); - if (kurl.protocolIs("http") || kurl.protocolIs("https")) - return true; - - return false; -} - -void DocLoader::setBlockNetworkImage(bool block) -{ - if (block == m_blockNetworkImage) - return; - - m_blockNetworkImage = block; - - if (!m_autoLoadImages || m_blockNetworkImage) - 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); - } - } -} -#endif - -CachePolicy DocLoader::cachePolicy() const -{ - return frame() ? frame()->loader()->subresourceCachePolicy() : CachePolicyVerify; -} - -void DocLoader::removeCachedResource(CachedResource* resource) const -{ -#ifndef NDEBUG - DocumentResourceMap::iterator it = m_documentResources.find(resource->url()); - if (it != m_documentResources.end()) - ASSERT(it->second.get() == resource); -#endif - 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(const CachedResource* res) -{ - if (res->isPrefetch()) - return; - - ++m_requestCount; -} - -void DocLoader::decrementRequestCount(const CachedResource* res) -{ - if (res->isPrefetch()) - return; - - --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]; - // Don't request preload if the resource already loaded normally (this will result in double load if the page is being reloaded with cached results ignored). - if (!cachedResource(m_doc->completeURL(preload.m_url))) - 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()->writer()->encoding() : charset; - - CachedResource* resource = requestResource(type, url, encoding, true); - if (!resource || (m_preloads && m_preloads->contains(resource))) - return; - resource->increasePreloadCount(); - - if (!m_preloads) - m_preloads = adoptPtr(new ListHashSet<CachedResource*>); - m_preloads->add(resource); - -#if PRELOAD_DEBUG - printf("PRELOADING %s\n", resource->url().latin1().data()); -#endif -} - -void DocLoader::clearPreloads() -{ -#if PRELOAD_DEBUG - printPreloadStats(); -#endif - if (!m_preloads) - return; - - 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_DEBUG -void 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 - -} |