diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:41 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:41 -0800 |
commit | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /WebCore/loader | |
parent | a65af38181ac7d34544586bdb5cd004de93897ad (diff) | |
download | external_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.zip external_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.tar.gz external_webkit-648161bb0edfc3d43db63caed5cc5213bc6cb78f.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/loader')
111 files changed, 0 insertions, 27515 deletions
diff --git a/WebCore/loader/Cache.cpp b/WebCore/loader/Cache.cpp deleted file mode 100644 index 7d30e5f..0000000 --- a/WebCore/loader/Cache.cpp +++ /dev/null @@ -1,724 +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, 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 "Cache.h" - -#include "CachedCSSStyleSheet.h" -#include "CachedFont.h" -#include "CachedImage.h" -#include "CachedScript.h" -#include "CachedXSLStyleSheet.h" -#include "DocLoader.h" -#include "Document.h" -#if USE(LOW_BANDWIDTH_DISPLAY) -#include "Frame.h" -#endif -#include "FrameLoader.h" -#include "FrameView.h" -#include "Image.h" -#include "ResourceHandle.h" -#include "SystemTime.h" -#include <stdio.h> - - -using namespace std; - -namespace WebCore { - -static const int cDefaultCacheCapacity = 8192 * 1024; -static const double cMinDelayBeforeLiveDecodedPrune = 1; // Seconds. -static const float cTargetPrunePercentage = .95f; // Percentage of capacity toward which we prune, to avoid immediately pruning again. -static const double cDefaultDecodedDataDeletionInterval = 0; - -Cache* cache() -{ - static Cache* staticCache = new Cache; - return staticCache; -} - -Cache::Cache() - : m_disabled(false) - , m_pruneEnabled(true) - , m_inPruneDeadResources(false) - , m_capacity(cDefaultCacheCapacity) - , m_minDeadCapacity(0) - , m_maxDeadCapacity(cDefaultCacheCapacity) - , m_deadDecodedDataDeletionInterval(cDefaultDecodedDataDeletionInterval) - , m_liveSize(0) - , m_deadSize(0) -{ -} - -static CachedResource* createResource(CachedResource::Type type, const KURL& url, const String& charset) -{ - switch (type) { - case CachedResource::ImageResource: - return new CachedImage(url.string()); - case CachedResource::CSSStyleSheet: - return new CachedCSSStyleSheet(url.string(), charset); - case CachedResource::Script: - return new CachedScript(url.string(), charset); - case CachedResource::FontResource: - return new CachedFont(url.string()); -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: - return new CachedXSLStyleSheet(url.string()); -#endif -#if ENABLE(XBL) - case CachedResource::XBLStyleSheet: - return new CachedXBLDocument(url.string()); -#endif - default: - break; - } - - return 0; -} - -CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Type type, const KURL& url, const String& charset, bool isPreload) -{ - // FIXME: Do we really need to special-case an empty URL? - // Would it be better to just go on with the cache code and let it fail later? - if (url.isEmpty()) - return 0; - - // Look up the resource in our map. - CachedResource* resource = m_resources.get(url.string()); - - if (resource) { - if (isPreload && !resource->isPreloaded()) - return 0; - if (FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(url, String(), docLoader->doc())) { - Document* doc = docLoader->doc(); - if(doc && !isPreload) - FrameLoader::reportLocalLoadFailed(doc->frame(), resource->url()); - return 0; - } - } else { - if (FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(url, String(), docLoader->doc())) { - Document* doc = docLoader->doc(); - if(doc && !isPreload) - FrameLoader::reportLocalLoadFailed(doc->frame(), url.string()); - return 0; - } - - // The resource does not exist. Create it. - resource = createResource(type, url, charset); - ASSERT(resource); - - // Pretend the resource is in the cache, to prevent it from being deleted during the load() call. - // FIXME: CachedResource should just use normal refcounting instead. - resource->setInCache(true); - - resource->load(docLoader); - - if (!disabled()) - m_resources.set(url.string(), resource); // The size will be added in later once the resource is loaded and calls back to us with the new size. - else { - // Kick the resource out of the cache, because the cache is disabled. - resource->setInCache(false); - resource->setDocLoader(docLoader); - if (resource->errorOccurred()) { - // We don't support immediate loads, but we do support immediate failure. - // In that case we should to delete the resource now and return 0 because otherwise - // it would leak if no ref/deref was ever done on it. - delete resource; - return 0; - } - } - } - - if (resource->type() != type) - return 0; - -#if USE(LOW_BANDWIDTH_DISPLAY) - // addLowBandwidthDisplayRequest() returns true if requesting CSS or JS during low bandwidth display. - // Here, return 0 to not block parsing or layout. - if (docLoader->frame() && docLoader->frame()->loader()->addLowBandwidthDisplayRequest(resource)) - return 0; -#endif - - if (!disabled()) { - // This will move the resource to the front of its LRU list and increase its access count. - resourceAccessed(resource); - } - - return resource; -} - -CachedCSSStyleSheet* Cache::requestUserCSSStyleSheet(DocLoader* docLoader, const String& url, const String& charset) -{ - CachedCSSStyleSheet* userSheet; - if (CachedResource* existing = m_resources.get(url)) { - if (existing->type() != CachedResource::CSSStyleSheet) - return 0; - userSheet = static_cast<CachedCSSStyleSheet*>(existing); - } else { - userSheet = new CachedCSSStyleSheet(url, charset); - - // Pretend the resource is in the cache, to prevent it from being deleted during the load() call. - // FIXME: CachedResource should just use normal refcounting instead. - userSheet->setInCache(true); - // Don't load incrementally, skip load checks, don't send resource load callbacks. - userSheet->load(docLoader, false, true, false); - if (!disabled()) - m_resources.set(url, userSheet); - else - userSheet->setInCache(false); - } - - if (!disabled()) { - // This will move the resource to the front of its LRU list and increase its access count. - resourceAccessed(userSheet); - } - - return userSheet; -} - -void Cache::revalidateResource(CachedResource* resource, DocLoader* docLoader) -{ - ASSERT(resource); - ASSERT(!disabled()); - if (resource->resourceToRevalidate()) - return; - if (!resource->canUseCacheValidator()) { - evict(resource); - return; - } - const String& url = resource->url(); - CachedResource* newResource = createResource(resource->type(), KURL(url), resource->encoding()); - newResource->setResourceToRevalidate(resource); - evict(resource); - m_resources.set(url, newResource); - newResource->setInCache(true); - resourceAccessed(newResource); - newResource->load(docLoader); -} - -void Cache::revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse& response) -{ - CachedResource* resource = revalidatingResource->resourceToRevalidate(); - ASSERT(resource); - ASSERT(!resource->inCache()); - ASSERT(resource->isLoaded()); - - evict(revalidatingResource); - - ASSERT(!m_resources.get(resource->url())); - m_resources.set(resource->url(), resource); - resource->setInCache(true); - resource->setExpirationDate(response.expirationDate()); - insertInLRUList(resource); - int delta = resource->size(); - if (resource->decodedSize() && resource->hasClients()) - insertInLiveDecodedResourcesList(resource); - if (delta) - adjustSize(resource->hasClients(), delta); - - revalidatingResource->switchClientsToRevalidatedResource(); - // this deletes the revalidating resource - revalidatingResource->clearResourceToRevalidate(); -} - -void Cache::revalidationFailed(CachedResource* revalidatingResource) -{ - ASSERT(revalidatingResource->resourceToRevalidate()); - revalidatingResource->clearResourceToRevalidate(); -} - -CachedResource* Cache::resourceForURL(const String& url) -{ - return m_resources.get(url); -} - -unsigned Cache::deadCapacity() const -{ - // Dead resource capacity is whatever space is not occupied by live resources, bounded by an independent minimum and maximum. - unsigned capacity = m_capacity - min(m_liveSize, m_capacity); // Start with available capacity. - capacity = max(capacity, m_minDeadCapacity); // Make sure it's above the minimum. - capacity = min(capacity, m_maxDeadCapacity); // Make sure it's below the maximum. - return capacity; -} - -unsigned Cache::liveCapacity() const -{ - // Live resource capacity is whatever is left over after calculating dead resource capacity. - return m_capacity - deadCapacity(); -} - -void Cache::pruneLiveResources() -{ - if (!m_pruneEnabled) - return; - - unsigned capacity = liveCapacity(); - if (capacity && m_liveSize <= capacity) - return; - - unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. - double currentTime = FrameView::currentPaintTimeStamp(); - if (!currentTime) // In case prune is called directly, outside of a Frame paint. - currentTime = WebCore::currentTime(); - - // Destroy any decoded data in live objects that we can. - // Start from the tail, since this is the least recently accessed of the objects. - CachedResource* current = m_liveDecodedResources.m_tail; - while (current) { - CachedResource* prev = current->m_prevInLiveResourcesList; - ASSERT(current->hasClients()); - if (current->isLoaded() && current->decodedSize()) { - // Check to see if the remaining resources are too new to prune. - double elapsedTime = currentTime - current->m_lastDecodedAccessTime; - if (elapsedTime < cMinDelayBeforeLiveDecodedPrune) - return; - - // Destroy our decoded data. This will remove us from - // m_liveDecodedResources, and possibly move us to a differnt LRU - // list in m_allResources. - current->destroyDecodedData(); - - if (targetSize && m_liveSize <= targetSize) - return; - } - current = prev; - } -} - -void Cache::pruneDeadResources() -{ - if (!m_pruneEnabled) - return; - - unsigned capacity = deadCapacity(); - if (capacity && m_deadSize <= capacity) - return; - - unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. - int size = m_allResources.size(); - bool canShrinkLRULists = true; - m_inPruneDeadResources = true; - for (int i = size - 1; i >= 0; i--) { - // Remove from the tail, since this is the least frequently accessed of the objects. - CachedResource* current = m_allResources[i].m_tail; - - // First flush all the decoded data in this queue. - while (current) { - CachedResource* prev = current->m_prevInAllResourcesList; - if (!current->hasClients() && !current->isPreloaded() && current->isLoaded() && current->decodedSize()) { - // Destroy our decoded data. This will remove us from - // m_liveDecodedResources, and possibly move us to a differnt - // LRU list in m_allResources. - current->destroyDecodedData(); - - if (targetSize && m_deadSize <= targetSize) { - m_inPruneDeadResources = false; - return; - } - } - current = prev; - } - - // Now evict objects from this queue. - current = m_allResources[i].m_tail; - while (current) { - CachedResource* prev = current->m_prevInAllResourcesList; - if (!current->hasClients() && !current->isPreloaded()) { - evict(current); - // If evict() caused pruneDeadResources() to be re-entered, bail out. This can happen when removing an - // SVG CachedImage that has subresources. - if (!m_inPruneDeadResources) - return; - - if (targetSize && m_deadSize <= targetSize) { - m_inPruneDeadResources = false; - return; - } - } - current = prev; - } - - // Shrink the vector back down so we don't waste time inspecting - // empty LRU lists on future prunes. - if (m_allResources[i].m_head) - canShrinkLRULists = false; - else if (canShrinkLRULists) - m_allResources.resize(i); - } - m_inPruneDeadResources = false; -} - -void Cache::setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes) -{ - ASSERT(minDeadBytes <= maxDeadBytes); - ASSERT(maxDeadBytes <= totalBytes); - m_minDeadCapacity = minDeadBytes; - m_maxDeadCapacity = maxDeadBytes; - m_capacity = totalBytes; - prune(); -} - -void Cache::evict(CachedResource* resource) -{ - // The resource may have already been removed by someone other than our caller, - // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bug.cgi?id=12479#c6>. - if (resource->inCache()) { - // Remove from the resource map. - m_resources.remove(resource->url()); - resource->setInCache(false); - - // Remove from the appropriate LRU list. - removeFromLRUList(resource); - removeFromLiveDecodedResourcesList(resource); - - // Notify all doc loaders that might be observing this object still that it has been - // extracted from the set of resources. - HashSet<DocLoader*>::iterator end = m_docLoaders.end(); - for (HashSet<DocLoader*>::iterator itr = m_docLoaders.begin(); itr != end; ++itr) - (*itr)->removeCachedResource(resource); - - // Subtract from our size totals. - int delta = -static_cast<int>(resource->size()); - if (delta) - adjustSize(resource->hasClients(), delta); - } else - ASSERT(m_resources.get(resource->url()) != resource); - - if (resource->canDelete()) - delete resource; -} - -void Cache::addDocLoader(DocLoader* docLoader) -{ - m_docLoaders.add(docLoader); -} - -void Cache::removeDocLoader(DocLoader* docLoader) -{ - m_docLoaders.remove(docLoader); -} - -static inline unsigned fastLog2(unsigned i) -{ - unsigned log2 = 0; - if (i & (i - 1)) - log2 += 1; - if (i >> 16) - log2 += 16, i >>= 16; - if (i >> 8) - log2 += 8, i >>= 8; - if (i >> 4) - log2 += 4, i >>= 4; - if (i >> 2) - log2 += 2, i >>= 2; - if (i >> 1) - log2 += 1; - return log2; -} - -Cache::LRUList* Cache::lruListFor(CachedResource* resource) -{ - unsigned accessCount = max(resource->accessCount(), 1U); - unsigned queueIndex = fastLog2(resource->size() / accessCount); -#ifndef NDEBUG - resource->m_lruIndex = queueIndex; -#endif - if (m_allResources.size() <= queueIndex) - m_allResources.grow(queueIndex + 1); - return &m_allResources[queueIndex]; -} - -void Cache::removeFromLRUList(CachedResource* resource) -{ - // If we've never been accessed, then we're brand new and not in any list. - if (resource->accessCount() == 0) - return; - -#ifndef NDEBUG - unsigned oldListIndex = resource->m_lruIndex; -#endif - - LRUList* list = lruListFor(resource); - -#ifndef NDEBUG - // Verify that the list we got is the list we want. - ASSERT(resource->m_lruIndex == oldListIndex); - - // Verify that we are in fact in this list. - bool found = false; - for (CachedResource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { - if (current == resource) { - found = true; - break; - } - } - ASSERT(found); -#endif - - CachedResource* next = resource->m_nextInAllResourcesList; - CachedResource* prev = resource->m_prevInAllResourcesList; - - if (next == 0 && prev == 0 && list->m_head != resource) - return; - - resource->m_nextInAllResourcesList = 0; - resource->m_prevInAllResourcesList = 0; - - if (next) - next->m_prevInAllResourcesList = prev; - else if (list->m_tail == resource) - list->m_tail = prev; - - if (prev) - prev->m_nextInAllResourcesList = next; - else if (list->m_head == resource) - list->m_head = next; -} - -void Cache::insertInLRUList(CachedResource* resource) -{ - // Make sure we aren't in some list already. - ASSERT(!resource->m_nextInAllResourcesList && !resource->m_prevInAllResourcesList); - ASSERT(resource->inCache()); - ASSERT(resource->accessCount() > 0); - - LRUList* list = lruListFor(resource); - - resource->m_nextInAllResourcesList = list->m_head; - if (list->m_head) - list->m_head->m_prevInAllResourcesList = resource; - list->m_head = resource; - - if (!resource->m_nextInAllResourcesList) - list->m_tail = resource; - -#ifndef NDEBUG - // Verify that we are in now in the list like we should be. - list = lruListFor(resource); - bool found = false; - for (CachedResource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { - if (current == resource) { - found = true; - break; - } - } - ASSERT(found); -#endif - -} - -void Cache::resourceAccessed(CachedResource* resource) -{ - ASSERT(resource->inCache()); - - // Need to make sure to remove before we increase the access count, since - // the queue will possibly change. - removeFromLRUList(resource); - - // Add to our access count. - resource->increaseAccessCount(); - - // Now insert into the new queue. - insertInLRUList(resource); -} - -void Cache::removeFromLiveDecodedResourcesList(CachedResource* resource) -{ - // If we've never been accessed, then we're brand new and not in any list. - if (!resource->m_inLiveDecodedResourcesList) - return; - resource->m_inLiveDecodedResourcesList = false; - -#ifndef NDEBUG - // Verify that we are in fact in this list. - bool found = false; - for (CachedResource* current = m_liveDecodedResources.m_head; current; current = current->m_nextInLiveResourcesList) { - if (current == resource) { - found = true; - break; - } - } - ASSERT(found); -#endif - - CachedResource* next = resource->m_nextInLiveResourcesList; - CachedResource* prev = resource->m_prevInLiveResourcesList; - - if (next == 0 && prev == 0 && m_liveDecodedResources.m_head != resource) - return; - - resource->m_nextInLiveResourcesList = 0; - resource->m_prevInLiveResourcesList = 0; - - if (next) - next->m_prevInLiveResourcesList = prev; - else if (m_liveDecodedResources.m_tail == resource) - m_liveDecodedResources.m_tail = prev; - - if (prev) - prev->m_nextInLiveResourcesList = next; - else if (m_liveDecodedResources.m_head == resource) - m_liveDecodedResources.m_head = next; -} - -void Cache::insertInLiveDecodedResourcesList(CachedResource* resource) -{ - // Make sure we aren't in the list already. - ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResourcesList && !resource->m_inLiveDecodedResourcesList); - resource->m_inLiveDecodedResourcesList = true; - - resource->m_nextInLiveResourcesList = m_liveDecodedResources.m_head; - if (m_liveDecodedResources.m_head) - m_liveDecodedResources.m_head->m_prevInLiveResourcesList = resource; - m_liveDecodedResources.m_head = resource; - - if (!resource->m_nextInLiveResourcesList) - m_liveDecodedResources.m_tail = resource; - -#ifndef NDEBUG - // Verify that we are in now in the list like we should be. - bool found = false; - for (CachedResource* current = m_liveDecodedResources.m_head; current; current = current->m_nextInLiveResourcesList) { - if (current == resource) { - found = true; - break; - } - } - ASSERT(found); -#endif - -} - -void Cache::addToLiveResourcesSize(CachedResource* resource) -{ - m_liveSize += resource->size(); - m_deadSize -= resource->size(); -} - -void Cache::removeFromLiveResourcesSize(CachedResource* resource) -{ - m_liveSize -= resource->size(); - m_deadSize += resource->size(); -} - -void Cache::adjustSize(bool live, int delta) -{ - if (live) { - ASSERT(delta >= 0 || ((int)m_liveSize + delta >= 0)); - m_liveSize += delta; - } else { - ASSERT(delta >= 0 || ((int)m_deadSize + delta >= 0)); - m_deadSize += delta; - } -} - -Cache::Statistics Cache::getStatistics() -{ - Statistics stats; - CachedResourceMap::iterator e = m_resources.end(); - for (CachedResourceMap::iterator i = m_resources.begin(); i != e; ++i) { - CachedResource *o = i->second; - switch (o->type()) { - case CachedResource::ImageResource: - stats.images.count++; - stats.images.size += o->size(); - stats.images.liveSize += o->hasClients() ? o->size() : 0; - stats.images.decodedSize += o->decodedSize(); - break; - - case CachedResource::CSSStyleSheet: - stats.cssStyleSheets.count++; - stats.cssStyleSheets.size += o->size(); - stats.cssStyleSheets.liveSize += o->hasClients() ? o->size() : 0; - stats.cssStyleSheets.decodedSize += o->decodedSize(); - break; - - case CachedResource::Script: - stats.scripts.count++; - stats.scripts.size += o->size(); - stats.scripts.liveSize += o->hasClients() ? o->size() : 0; - stats.scripts.decodedSize += o->decodedSize(); - break; -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: - stats.xslStyleSheets.count++; - stats.xslStyleSheets.size += o->size(); - stats.xslStyleSheets.liveSize += o->hasClients() ? o->size() : 0; - stats.xslStyleSheets.decodedSize += o->decodedSize(); - break; -#endif - case CachedResource::FontResource: - stats.fonts.count++; - stats.fonts.size += o->size(); - stats.fonts.liveSize += o->hasClients() ? o->size() : 0; - stats.fonts.decodedSize += o->decodedSize(); - break; -#if ENABLE(XBL) - case CachedResource::XBL: - stats.xblDocs.count++; - stats.xblDocs.size += o->size(); - stats.xblDocs.liveSize += o->hasClients() ? o->size() : 0; - stats.xblDocs.decodedSize += o->decodedSize(); - break; -#endif - default: - break; - } - } - - return stats; -} - -void Cache::setDisabled(bool disabled) -{ - m_disabled = disabled; - if (!m_disabled) - return; - - for (;;) { - CachedResourceMap::iterator i = m_resources.begin(); - if (i == m_resources.end()) - break; - evict(i->second); - } -} - -#ifndef NDEBUG -void Cache::dumpLRULists(bool includeLive) const -{ - printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n"); - - int size = m_allResources.size(); - for (int i = size - 1; i >= 0; i--) { - printf("\n\nList %d: ", i); - CachedResource* current = m_allResources[i].m_tail; - while (current) { - CachedResource* prev = current->m_prevInAllResourcesList; - if (includeLive || !current->hasClients()) - printf("(%.1fK, %.1fK, %uA, %dR); ", current->decodedSize() / 1024.0f, current->encodedSize() / 1024.0f, current->accessCount(), current->hasClients()); - current = prev; - } - } -} -#endif - -} // namespace WebCore diff --git a/WebCore/loader/Cache.h b/WebCore/loader/Cache.h deleted file mode 100644 index ec0ea0e..0000000 --- a/WebCore/loader/Cache.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - 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. - - 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. -*/ - -#ifndef Cache_h -#define Cache_h - -#include "CachePolicy.h" -#include "CachedResource.h" -#include "PlatformString.h" -#include "StringHash.h" -#include "loader.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class CachedCSSStyleSheet; -class CachedResource; -class DocLoader; -class KURL; - -// This cache holds subresources used by Web pages: images, scripts, stylesheets, etc. - -// The cache keeps a flexible but bounded window of dead resources that grows/shrinks -// depending on the live resource load. Here's an example of cache growth over time, -// with a min dead resource capacity of 25% and a max dead resource capacity of 50%: - -// |-----| Dead: - -// |----------| Live: + -// --|----------| Cache boundary: | (objects outside this mark have been evicted) -// --|----------++++++++++| -// -------|-----+++++++++++++++| -// -------|-----+++++++++++++++|+++++ - -class Cache : Noncopyable { -public: - friend Cache* cache(); - - typedef HashMap<String, CachedResource*> CachedResourceMap; - - struct LRUList { - CachedResource* m_head; - CachedResource* m_tail; - LRUList() : m_head(0), m_tail(0) { } - }; - - struct TypeStatistic { - int count; - int size; - int liveSize; - int decodedSize; - TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0) { } - }; - - struct Statistics { - TypeStatistic images; - TypeStatistic cssStyleSheets; - TypeStatistic scripts; -#if ENABLE(XSLT) - TypeStatistic xslStyleSheets; -#endif -#if ENABLE(XBL) - TypeStatistic xblDocs; -#endif - TypeStatistic fonts; - }; - - // The loader that fetches resources. - Loader* loader() { return &m_loader; } - - // Request resources from the cache. A load will be initiated and a cache object created if the object is not - // found in the cache. - CachedResource* requestResource(DocLoader*, CachedResource::Type, const KURL& url, const String& charset, bool isPreload = false); - - CachedCSSStyleSheet* requestUserCSSStyleSheet(DocLoader*, const String& url, const String& charset); - - void revalidateResource(CachedResource*, DocLoader*); - void revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse&); - void revalidationFailed(CachedResource* revalidatingResource); - - // Sets the cache's memory capacities, in bytes. These will hold only approximately, - // since the decoded cost of resources like scripts and stylesheets is not known. - // - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure. - // - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure. - // - totalBytes: The maximum number of bytes that the cache should consume overall. - void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes); - - // Turn the cache on and off. Disabling the cache will remove all resources from the cache. They may - // still live on if they are referenced by some Web page though. - void setDisabled(bool); - bool disabled() const { return m_disabled; } - - void setPruneEnabled(bool enabled) { m_pruneEnabled = enabled; } - void prune() - { - if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize <= m_maxDeadCapacity) // Fast path. - return; - - pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live. - pruneLiveResources(); - } - - void setDeadDecodedDataDeletionInterval(double interval) { m_deadDecodedDataDeletionInterval = interval; } - double deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; } - - // Remove an existing cache entry from both the resource map and from the LRU list. - void remove(CachedResource* resource) { evict(resource); } - - void addDocLoader(DocLoader*); - void removeDocLoader(DocLoader*); - - CachedResource* resourceForURL(const String&); - - // Calls to put the cached resource into and out of LRU lists. - void insertInLRUList(CachedResource*); - void removeFromLRUList(CachedResource*); - - // Called to adjust the cache totals when a resource changes size. - void adjustSize(bool live, int delta); - - // Track decoded resources that are in the cache and referenced by a Web page. - void insertInLiveDecodedResourcesList(CachedResource*); - void removeFromLiveDecodedResourcesList(CachedResource*); - - void addToLiveResourcesSize(CachedResource*); - void removeFromLiveResourcesSize(CachedResource*); - - // Function to collect cache statistics for the caches window in the Safari Debug menu. - Statistics getStatistics(); - -#ifdef ANDROID_INSTRUMENT - unsigned getLiveSize() { return m_liveSize; } - unsigned getDeadSize() { return m_deadSize; } -#endif - -private: - Cache(); - ~Cache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. - - LRUList* lruListFor(CachedResource*); - void resourceAccessed(CachedResource*); -#ifndef NDEBUG - void dumpLRULists(bool includeLive) const; -#endif - - unsigned liveCapacity() const; - unsigned deadCapacity() const; - - void pruneDeadResources(); // Flush decoded and encoded data from resources not referenced by Web pages. - void pruneLiveResources(); // Flush decoded data from resources still referenced by Web pages. - - void evict(CachedResource*); - - // Member variables. - HashSet<DocLoader*> m_docLoaders; - Loader m_loader; - - bool m_disabled; // Whether or not the cache is enabled. - bool m_pruneEnabled; - bool m_inPruneDeadResources; - - unsigned m_capacity; - unsigned m_minDeadCapacity; - unsigned m_maxDeadCapacity; - double m_deadDecodedDataDeletionInterval; - - unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache. - unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache. - - // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold - // more resources than the cached resource map, since it can also hold "stale" muiltiple versions of objects that are - // waiting to die when the clients referencing them go away. - Vector<LRUList, 32> m_allResources; - - // List just for live resources with decoded data. Access to this list is based off of painting the resource. - LRUList m_liveDecodedResources; - - // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being - // referenced by a Web page). - HashMap<String, CachedResource*> m_resources; -}; - -// Function to obtain the global cache. -Cache* cache(); - -} - -#endif diff --git a/WebCore/loader/CachePolicy.h b/WebCore/loader/CachePolicy.h deleted file mode 100644 index 16af78a..0000000 --- a/WebCore/loader/CachePolicy.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CachePolicy_h -#define CachePolicy_h - -namespace WebCore { - - enum CachePolicy { - CachePolicyCache, - CachePolicyVerify, - CachePolicyRefresh, - CachePolicyReload - }; - -} - -#endif diff --git a/WebCore/loader/CachedCSSStyleSheet.cpp b/WebCore/loader/CachedCSSStyleSheet.cpp deleted file mode 100644 index 9059f25..0000000 --- a/WebCore/loader/CachedCSSStyleSheet.cpp +++ /dev/null @@ -1,127 +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) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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 "CachedCSSStyleSheet.h" - -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "TextResourceDecoder.h" -#include "loader.h" -#include <wtf/Vector.h> - -namespace WebCore { - -CachedCSSStyleSheet::CachedCSSStyleSheet(const String& url, const String& charset) - : CachedResource(url, CSSStyleSheet) - , m_decoder(TextResourceDecoder::create("text/css", charset)) -{ - // Prefer text/css but accept any type (dell.com serves a stylesheet - // as text/html; see <http://bugs.webkit.org/show_bug.cgi?id=11451>). - setAccept("text/css,*/*;q=0.1"); -} - -CachedCSSStyleSheet::~CachedCSSStyleSheet() -{ -} - -void CachedCSSStyleSheet::addClient(CachedResourceClient *c) -{ - CachedResource::addClient(c); - - if (!m_loading) - c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), this); -} - -void CachedCSSStyleSheet::setEncoding(const String& chs) -{ - m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader); -} - -String CachedCSSStyleSheet::encoding() const -{ - return m_decoder->encoding().name(); -} - -void CachedCSSStyleSheet::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - if (m_data.get()) { - m_sheet = m_decoder->decode(m_data->data(), encodedSize()); - m_sheet += m_decoder->flush(); -#ifdef ANDROID_FIX // FIXME Newer webkit makes decode temporary; remove on webkit update - // report decoded size too - setDecodedSize(m_sheet.length() * sizeof(UChar)); -#endif - } - m_loading = false; - checkNotify(); -} - -void CachedCSSStyleSheet::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->setCSSStyleSheet(m_response.url().string(), m_decoder->encoding().name(), this); - -#if USE(LOW_BANDWIDTH_DISPLAY) - // if checkNotify() is called from error(), client's setCSSStyleSheet(...) - // can't find "this" from url, so they can't do clean up if needed. - // call notifyFinished() to make sure they have a chance. - CachedResourceClientWalker n(m_clients); - while (CachedResourceClient* s = n.next()) - s->notifyFinished(this); -#endif -} - -void CachedCSSStyleSheet::error() -{ - m_loading = false; - m_errorOccurred = true; - checkNotify(); -} - -bool CachedCSSStyleSheet::canUseSheet(bool enforceMIMEType) const -{ - if (errorOccurred()) - return false; - - if (!enforceMIMEType) - return true; - - // This check exactly matches Firefox. - String mimeType = response().mimeType(); - return mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type"); -} - -} diff --git a/WebCore/loader/CachedCSSStyleSheet.h b/WebCore/loader/CachedCSSStyleSheet.h deleted file mode 100644 index b9129ba..0000000 --- a/WebCore/loader/CachedCSSStyleSheet.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedCSSStyleSheet_h -#define CachedCSSStyleSheet_h - -#include "CachedResource.h" -#include "TextEncoding.h" -#include <wtf/Vector.h> - -namespace WebCore { - - class DocLoader; - class TextResourceDecoder; - - class CachedCSSStyleSheet : public CachedResource { - public: - CachedCSSStyleSheet(const String& URL, const String& charset); - virtual ~CachedCSSStyleSheet(); - - const String sheetText(bool enforceMIMEType = true) const { return canUseSheet(enforceMIMEType) ? m_sheet : ""; } - - virtual void addClient(CachedResourceClient*); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(); - - virtual bool schedule() const { return true; } - - void checkNotify(); - - private: - bool canUseSheet(bool enforceMIMEType) const; - - protected: - String m_sheet; - RefPtr<TextResourceDecoder> m_decoder; - }; - -} - -#endif diff --git a/WebCore/loader/CachedFont.cpp b/WebCore/loader/CachedFont.cpp deleted file mode 100644 index 20479ef..0000000 --- a/WebCore/loader/CachedFont.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CachedFont.h" - -#include "Cache.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "DOMImplementation.h" -#include "FontPlatformData.h" -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) -#include "FontCustomPlatformData.h" -#endif -#include "TextResourceDecoder.h" -#include "loader.h" -#include <wtf/Vector.h> - -#if ENABLE(SVG_FONTS) -#include "HTMLNames.h" -#include "NodeList.h" -#include "SVGElement.h" -#include "SVGFontElement.h" -#include "SVGGElement.h" -#endif - -namespace WebCore { - -CachedFont::CachedFont(const String &url) - : CachedResource(url, FontResource) - , m_fontData(0) - , m_loadInitiated(false) -#if ENABLE(SVG_FONTS) - , m_isSVGFont(false) -#endif -{ -} - -CachedFont::~CachedFont() -{ -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) - delete m_fontData; -#endif -} - -void CachedFont::load(DocLoader* docLoader) -{ - // Don't load the file yet. Wait for an access before triggering the load. - m_loading = true; -} - -void CachedFont::addClient(CachedResourceClient* c) -{ - CachedResource::addClient(c); - - if (!m_loading) - c->fontLoaded(this); -} - -void CachedFont::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - m_loading = false; - checkNotify(); -} - -void CachedFont::beginLoadIfNeeded(DocLoader* dl) -{ - if (!m_loadInitiated) { - m_loadInitiated = true; - cache()->loader()->load(dl, this, false); - } -} - -bool CachedFont::ensureCustomFontData() -{ -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) -#if ENABLE(SVG_FONTS) - ASSERT(!m_isSVGFont); -#endif - if (!m_fontData && !m_errorOccurred && !m_loading && m_data) { - m_fontData = createFontCustomPlatformData(m_data.get()); - if (!m_fontData) - m_errorOccurred = true; - } -#endif - return m_fontData; -} - -FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontRenderingMode renderingMode) -{ -#if ENABLE(SVG_FONTS) - if (m_externalSVGDocument) - return FontPlatformData(size, bold, italic); -#endif -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(SGL) - ASSERT(m_fontData); - return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, renderingMode); -#else - return FontPlatformData(); -#endif -} - -#if ENABLE(SVG_FONTS) -bool CachedFont::ensureSVGFontData() -{ - ASSERT(m_isSVGFont); - if (!m_externalSVGDocument && !m_errorOccurred && !m_loading && m_data) { - m_externalSVGDocument = SVGDocument::create(0); - m_externalSVGDocument->open(); - - RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml"); - m_externalSVGDocument->write(decoder->decode(m_data->data(), m_data->size())); - if (decoder->sawError()) { - m_externalSVGDocument.clear(); - return 0; - } - - m_externalSVGDocument->finishParsing(); - m_externalSVGDocument->close(); - } - - return m_externalSVGDocument; -} - -SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const -{ - ASSERT(m_isSVGFont); - RefPtr<NodeList> list = m_externalSVGDocument->getElementsByTagName(SVGNames::fontTag.localName()); - if (!list) - return 0; - - unsigned fonts = list->length(); - for (unsigned i = 0; i < fonts; ++i) { - Node* node = list->item(i); - ASSERT(node); - - if (static_cast<Element*>(node)->getAttribute(HTMLNames::idAttr) != fontName) - continue; - - ASSERT(node->hasTagName(SVGNames::fontTag)); - return static_cast<SVGFontElement*>(node); - } - - return 0; -} -#endif - -void CachedFont::allClientsRemoved() -{ -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) - if (m_fontData) { - delete m_fontData; - m_fontData = 0; - } -#endif -} - -void CachedFont::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->fontLoaded(this); -} - - -void CachedFont::error() -{ - m_loading = false; - m_errorOccurred = true; - checkNotify(); -} - -} diff --git a/WebCore/loader/CachedFont.h b/WebCore/loader/CachedFont.h deleted file mode 100644 index fd19cdb..0000000 --- a/WebCore/loader/CachedFont.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CachedFont_h -#define CachedFont_h - -#include "CachedResource.h" -#include "FontRenderingMode.h" -#include <wtf/Vector.h> - -#if ENABLE(SVG_FONTS) -#include "SVGElement.h" -#include "SVGDocument.h" -#endif - -namespace WebCore { - -class DocLoader; -class Cache; -class FontCustomPlatformData; -class FontPlatformData; -class SVGFontElement; - -class CachedFont : public CachedResource { -public: - CachedFont(const String& url); - virtual ~CachedFont(); - - virtual void load(DocLoader* docLoader); - - virtual void addClient(CachedResourceClient*); - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(); - - virtual void allClientsRemoved(); - - virtual bool schedule() const { return true; } - - void checkNotify(); - - void beginLoadIfNeeded(DocLoader* dl); - - bool ensureCustomFontData(); - FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode); - -#if ENABLE(SVG_FONTS) - bool isSVGFont() const { return m_isSVGFont; } - void setSVGFont(bool isSVG) { m_isSVGFont = isSVG; } - bool ensureSVGFontData(); - SVGFontElement* getSVGFontById(const String&) const; -#endif - -private: - FontCustomPlatformData* m_fontData; - bool m_loadInitiated; - -#if ENABLE(SVG_FONTS) - bool m_isSVGFont; - RefPtr<SVGDocument> m_externalSVGDocument; -#endif - - friend class Cache; -}; - -} - -#endif diff --git a/WebCore/loader/CachedImage.cpp b/WebCore/loader/CachedImage.cpp deleted file mode 100644 index 3327c38..0000000 --- a/WebCore/loader/CachedImage.cpp +++ /dev/null @@ -1,364 +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) 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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" -#include "CachedImage.h" - -#include "BitmapImage.h" -#include "Cache.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "DocLoader.h" -#include "Frame.h" -#include "FrameView.h" -#include "Request.h" -#include "Settings.h" -#include "SystemTime.h" -#include <wtf/Vector.h> - -#if PLATFORM(CG) -#include "PDFDocumentImage.h" -#endif - -#if ENABLE(SVG_AS_IMAGE) -#include "SVGImage.h" -#endif - -using std::max; - -namespace WebCore { - -CachedImage::CachedImage(const String& url) - : CachedResource(url, ImageResource) - , m_image(0) - , m_decodedDataDeletionTimer(this, &CachedImage::decodedDataDeletionTimerFired) -{ - m_status = Unknown; -} - -CachedImage::CachedImage(Image* image) - : CachedResource(String(), ImageResource) - , m_image(image) - , m_decodedDataDeletionTimer(this, &CachedImage::decodedDataDeletionTimerFired) -{ - m_status = Cached; - m_loading = false; -} - -CachedImage::~CachedImage() -{ -} - -void CachedImage::decodedDataDeletionTimerFired(Timer<CachedImage>*) -{ - ASSERT(!hasClients()); - destroyDecodedData(); -} - -void CachedImage::load(DocLoader* docLoader) -{ -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (!docLoader || (docLoader->autoLoadImages() && !docLoader->shouldBlockNetworkImage(m_url))) -#else - if (!docLoader || docLoader->autoLoadImages()) -#endif - CachedResource::load(docLoader, true, false, true); - else - m_loading = false; -} - -void CachedImage::addClient(CachedResourceClient* c) -{ - CachedResource::addClient(c); - - if (m_decodedDataDeletionTimer.isActive()) - m_decodedDataDeletionTimer.stop(); - - if (m_image && !m_image->rect().isEmpty()) - c->imageChanged(this); - - if (!m_loading) - c->notifyFinished(this); -} - -void CachedImage::allClientsRemoved() -{ - if (m_image && !m_errorOccurred) - m_image->resetAnimation(); - if (double interval = cache()->deadDecodedDataDeletionInterval()) - m_decodedDataDeletionTimer.startOneShot(interval); -} - -static Image* brokenImage() -{ - static RefPtr<Image> brokenImage; - if (!brokenImage) - brokenImage = Image::loadPlatformResource("missingImage"); - return brokenImage.get(); -} - -static Image* nullImage() -{ - static RefPtr<BitmapImage> nullImage = BitmapImage::create(); - return nullImage.get(); -} - -Image* CachedImage::image() const -{ - if (m_errorOccurred) - return brokenImage(); - - if (m_image) - return m_image.get(); - - return nullImage(); -} - -void CachedImage::setImageContainerSize(const IntSize& containerSize) -{ - if (m_image) - m_image->setContainerSize(containerSize); -} - -bool CachedImage::usesImageContainerSize() const -{ - if (m_image) - return m_image->usesContainerSize(); - - return false; -} - -bool CachedImage::imageHasRelativeWidth() const -{ - if (m_image) - return m_image->hasRelativeWidth(); - - return false; -} - -bool CachedImage::imageHasRelativeHeight() const -{ - if (m_image) - return m_image->hasRelativeHeight(); - - return false; -} - -IntSize CachedImage::imageSize(float multiplier) const -{ - if (!m_image) - return IntSize(); - if (multiplier == 1.0f) - return m_image->size(); - - // Don't let images that have a width/height >= 1 shrink below 1 when zoomed. - bool hasWidth = m_image->size().width() > 0; - bool hasHeight = m_image->size().height() > 0; - int width = m_image->size().width() * (m_image->hasRelativeWidth() ? 1.0f : multiplier); - int height = m_image->size().height() * (m_image->hasRelativeHeight() ? 1.0f : multiplier); - if (hasWidth) - width = max(1, width); - if (hasHeight) - height = max(1, height); - return IntSize(width, height); -} - -IntRect CachedImage::imageRect(float multiplier) const -{ - if (!m_image) - return IntRect(); - if (multiplier == 1.0f || (!m_image->hasRelativeWidth() && !m_image->hasRelativeHeight())) - return m_image->rect(); - - float widthMultiplier = (m_image->hasRelativeWidth() ? 1.0f : multiplier); - float heightMultiplier = (m_image->hasRelativeHeight() ? 1.0f : multiplier); - - // Don't let images that have a width/height >= 1 shrink below 1 when zoomed. - bool hasWidth = m_image->rect().width() > 0; - bool hasHeight = m_image->rect().height() > 0; - - int width = static_cast<int>(m_image->rect().width() * widthMultiplier); - int height = static_cast<int>(m_image->rect().height() * heightMultiplier); - if (hasWidth) - width = max(1, width); - if (hasHeight) - height = max(1, height); - - int x = static_cast<int>(m_image->rect().x() * widthMultiplier); - int y = static_cast<int>(m_image->rect().y() * heightMultiplier); - - return IntRect(x, y, width, height); -} - -void CachedImage::notifyObservers() -{ - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->imageChanged(this); -} - -void CachedImage::clear() -{ - destroyDecodedData(); - m_image = 0; - setEncodedSize(0); -} - -inline void CachedImage::createImage() -{ - // Create the image if it doesn't yet exist. - if (m_image) - return; -#if PLATFORM(CG) - if (m_response.mimeType() == "application/pdf") { - m_image = PDFDocumentImage::create(); - return; - } -#endif -#if ENABLE(SVG_AS_IMAGE) - if (m_response.mimeType() == "image/svg+xml") { - m_image = SVGImage::create(this); - return; - } -#endif - m_image = BitmapImage::create(this); -#if PLATFORM(SGL) - m_image->setURL(url()); -#endif -} - -size_t CachedImage::maximumDecodedImageSize() -{ - Frame* frame = m_request ? m_request->docLoader()->frame() : 0; - if (!frame) - return 0; - Settings* settings = frame->settings(); - return settings ? settings->maximumDecodedImageSize() : 0; -} - -void CachedImage::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - m_data = data; - - createImage(); - - bool sizeAvailable = false; - - // Have the image update its data from its internal buffer. - // It will not do anything now, but will delay decoding until - // queried for info (like size or specific image frames). - sizeAvailable = m_image->setData(m_data, allDataReceived); - - // Go ahead and tell our observers to try to draw if we have either - // received all the data or the size is known. Each chunk from the - // network causes observers to repaint, which will force that chunk - // to decode. - if (sizeAvailable || allDataReceived) { - size_t maxDecodedImageSize = maximumDecodedImageSize(); - IntSize s = imageSize(1.0f); - size_t estimatedDecodedImageSize = s.width() * s.height() * 4; // no overflow check - if (m_image->isNull() || (maxDecodedImageSize > 0 && estimatedDecodedImageSize > maxDecodedImageSize)) { - error(); - if (inCache()) - cache()->remove(this); - return; - } - - notifyObservers(); - - if (m_image) - setEncodedSize(m_image->data() ? m_image->data()->size() : 0); - } - - if (allDataReceived) { - m_loading = false; - checkNotify(); - } -} - -void CachedImage::error() -{ - clear(); - m_errorOccurred = true; - notifyObservers(); - m_loading = false; - checkNotify(); -} - -void CachedImage::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - -void CachedImage::destroyDecodedData() -{ - if (m_image && !m_errorOccurred) - m_image->destroyDecodedData(); -} - -void CachedImage::decodedSizeChanged(const Image* image, int delta) -{ - if (image != m_image) - return; - - setDecodedSize(decodedSize() + delta); -} - -void CachedImage::didDraw(const Image* image) -{ - if (image != m_image) - return; - - double timeStamp = FrameView::currentPaintTimeStamp(); - if (!timeStamp) // If didDraw is called outside of a Frame paint. - timeStamp = currentTime(); - - CachedResource::didAccessDecodedData(timeStamp); -} - -bool CachedImage::shouldPauseAnimation(const Image* image) -{ - if (image != m_image) - return false; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) { - if (c->willRenderImage(this)) - return false; - } - - return true; -} - -void CachedImage::animationAdvanced(const Image* image) -{ - if (image == m_image) - notifyObservers(); -} - -} //namespace WebCore diff --git a/WebCore/loader/CachedImage.h b/WebCore/loader/CachedImage.h deleted file mode 100644 index f24e2fb..0000000 --- a/WebCore/loader/CachedImage.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef CachedImage_h -#define CachedImage_h - -#include "CachedResource.h" -#include "ImageObserver.h" -#include "Image.h" -#include "IntRect.h" -#include "Timer.h" -#include <wtf/Vector.h> - -namespace WebCore { - -class DocLoader; -class Cache; - -class CachedImage : public CachedResource, public ImageObserver { - friend class Cache; - -public: - CachedImage(const String& url); - CachedImage(Image*); - virtual ~CachedImage(); - - virtual void load(DocLoader* docLoader); - - Image* image() const; - - bool canRender(float multiplier) const { return !errorOccurred() && !imageSize(multiplier).isEmpty(); } - - // These are only used for SVGImage right now - void setImageContainerSize(const IntSize&); - bool usesImageContainerSize() const; - bool imageHasRelativeWidth() const; - bool imageHasRelativeHeight() const; - - // Both of these methods take a zoom multiplier that can be used to increase the natural size of the image by the - // zoom. - IntSize imageSize(float multiplier) const; // returns the size of the complete image. - IntRect imageRect(float multiplier) const; // The size of the currently decoded portion of the image. - - virtual void addClient(CachedResourceClient*); - - virtual void allClientsRemoved(); - virtual void destroyDecodedData(); - - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(); - - virtual bool schedule() const { return true; } - - void checkNotify(); - - virtual bool isImage() const { return true; } - - void clear(); - - bool stillNeedsLoad() const { return !m_errorOccurred && m_status == Unknown && m_loading == false; } - void load(); - - // ImageObserver - virtual void decodedSizeChanged(const Image* image, int delta); - virtual void didDraw(const Image*); - - virtual bool shouldPauseAnimation(const Image*); - virtual void animationAdvanced(const Image*); - -private: - void createImage(); - size_t maximumDecodedImageSize(); - void notifyObservers(); - void decodedDataDeletionTimerFired(Timer<CachedImage>*); - - RefPtr<Image> m_image; - Timer<CachedImage> m_decodedDataDeletionTimer; -}; - -} - -#endif diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp deleted file mode 100644 index 6d0af9b..0000000 --- a/WebCore/loader/CachedResource.cpp +++ /dev/null @@ -1,316 +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) 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., 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 "Request.h" -#include "SystemTime.h" -#include <wtf/RefCountedLeakCounter.h> -#include <wtf/Vector.h> - -using namespace WTF; - -namespace WebCore { - -#ifndef NDEBUG -static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource"); -#endif - -CachedResource::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) -{ - 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; - String cacheControl = m_response.httpHeaderField("Cache-Control"); - // FIXME: It would be better to tokenize the field. - if (cachePolicy == CachePolicyCache) - return !cacheControl.isEmpty() && (cacheControl.contains("no-cache", false) || (isExpired() && cacheControl.contains("must-revalidate", false))); - return isExpired() || cacheControl.contains("no-cache", false); -} - -} diff --git a/WebCore/loader/CachedResource.h b/WebCore/loader/CachedResource.h deleted file mode 100644 index c56a889..0000000 --- a/WebCore/loader/CachedResource.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef CachedResource_h -#define CachedResource_h - -#include "CachePolicy.h" -#include "PlatformString.h" -#include "ResourceResponse.h" -#include "SharedBuffer.h" -#include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> -#include <wtf/Vector.h> -#include <time.h> - -namespace WebCore { - -class Cache; -class CachedResourceClient; -class CachedResourceHandleBase; -class DocLoader; -class Request; - -// A resource that is held in the cache. Classes who want to use this object should derive -// from CachedResourceClient, to get the function calls in case the requested data has arrived. -// This class also does the actual communication with the loader to obtain the resource from the network. -class CachedResource { - friend class Cache; - -public: - enum Type { - ImageResource, - CSSStyleSheet, - Script, - FontResource -#if ENABLE(XSLT) - , XSLStyleSheet -#endif -#if ENABLE(XBL) - , XBL -#endif - }; - - enum Status { - NotCached, // this URL is not cached - Unknown, // let cache decide what to do with it - New, // inserting new item - Pending, // only partially loaded - Cached // regular case - }; - - CachedResource(const String& url, Type); - virtual ~CachedResource(); - - virtual void load(DocLoader* docLoader) { load(docLoader, false, false, true); } - void load(DocLoader*, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks); - - virtual void setEncoding(const String&) { } - virtual String encoding() const { return String(); } - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived) = 0; - virtual void error() = 0; - - const String &url() const { return m_url; } - Type type() const { return m_type; } - - virtual void addClient(CachedResourceClient*); - void removeClient(CachedResourceClient*); - bool hasClients() const { return !m_clients.isEmpty(); } - void deleteIfPossible(); - - enum PreloadResult { - PreloadNotReferenced, - PreloadReferenced, - PreloadReferencedWhileLoading, - PreloadReferencedWhileComplete - }; - PreloadResult preloadResult() const { return m_preloadResult; } - void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; } - - virtual void allClientsRemoved() { }; - - unsigned count() const { return m_clients.size(); } - - Status status() const { return m_status; } - - unsigned size() const { return encodedSize() + decodedSize(); } - unsigned encodedSize() const { return m_encodedSize; } - unsigned decodedSize() const { return m_decodedSize; } - - bool isLoaded() const { return !m_loading; } - void setLoading(bool b) { m_loading = b; } - - virtual bool isImage() const { return false; } - - unsigned accessCount() const { return m_accessCount; } - void increaseAccessCount() { m_accessCount++; } - - // Computes the status of an object after loading. - // Updates the expire date on the cache entry file - void finish(); - - // Called by the cache if the object has been removed from the cache - // while still being referenced. This means the object should delete itself - // if the number of clients observing it ever drops to 0. - void setInCache(bool b) { m_inCache = b; } - bool inCache() const { return m_inCache; } - - void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } - bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } - - void setRequest(Request*); - - SharedBuffer* data() const { return m_data.get(); } - - void setResponse(const ResourceResponse&); - const ResourceResponse& response() const { return m_response; } - - bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_isBeingRevalidated; } - - bool isExpired() const; - - virtual bool schedule() const { return false; } - - // List of acceptable MIME types seperated by ",". - // A MIME type may contain a wildcard, e.g. "text/*". - String accept() const { return m_accept; } - void setAccept(const String& accept) { m_accept = accept; } - - bool errorOccurred() const { return m_errorOccurred; } - bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } - - virtual void destroyDecodedData() {}; - - void setDocLoader(DocLoader* docLoader) { m_docLoader = docLoader; } - - bool isPreloaded() const { return m_preloadCount; } - void increasePreloadCount() { ++m_preloadCount; } - void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } - - void registerHandle(CachedResourceHandleBase* h) { ++m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.add(h); } - void unregisterHandle(CachedResourceHandleBase* h) { --m_handleCount; if (m_resourceToRevalidate) m_handlesToRevalidate.remove(h); if (!m_handleCount) deleteIfPossible(); } - - bool canUseCacheValidator() const; - bool mustRevalidate(CachePolicy) const; - bool isCacheValidator() const { return m_resourceToRevalidate; } - CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } - -protected: - void setEncodedSize(unsigned); - void setDecodedSize(unsigned); - void didAccessDecodedData(double timeStamp); - - HashCountedSet<CachedResourceClient*> m_clients; - - String m_url; - String m_accept; - Request* m_request; - - ResourceResponse m_response; - RefPtr<SharedBuffer> m_data; - - Type m_type; - Status m_status; - - bool m_errorOccurred; - -private: - // These are called by the friendly Cache only - void setResourceToRevalidate(CachedResource*); - void switchClientsToRevalidatedResource(); - void clearResourceToRevalidate(); - void setExpirationDate(time_t expirationDate) { m_expirationDate = expirationDate; } - - unsigned m_encodedSize; - unsigned m_decodedSize; - unsigned m_accessCount; - unsigned m_inLiveDecodedResourcesList; - double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache - - bool m_sendResourceLoadCallbacks; - - unsigned m_preloadCount; - PreloadResult m_preloadResult; - bool m_requestedFromNetworkingLayer; - -protected: - bool m_inCache; - bool m_loading; - bool m_expireDateChanged; -#ifndef NDEBUG - bool m_deleted; - unsigned m_lruIndex; -#endif - -private: - CachedResource* m_nextInAllResourcesList; - CachedResource* m_prevInAllResourcesList; - - CachedResource* m_nextInLiveResourcesList; - CachedResource* m_prevInLiveResourcesList; - - DocLoader* m_docLoader; // only non-0 for resources that are not in the cache - - unsigned m_handleCount; - // If this field is non-null we are using the resource as a proxy for checking whether an existing resource is still up to date - // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved - // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this - // resources becomes normal resource load. - CachedResource* m_resourceToRevalidate; - bool m_isBeingRevalidated; - // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. - HashSet<CachedResourceHandleBase*> m_handlesToRevalidate; - - time_t m_expirationDate; -}; - -} - -#endif diff --git a/WebCore/loader/CachedResourceClient.h b/WebCore/loader/CachedResourceClient.h deleted file mode 100644 index 1d8d45e..0000000 --- a/WebCore/loader/CachedResourceClient.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedResourceClient_h -#define CachedResourceClient_h - -#if ENABLE(XBL) -namespace XBL { - class XBLDocument; -} -#endif - -namespace WebCore { - - class CachedCSSStyleSheet; - class CachedFont; - class CachedResource; - class CachedImage; - class String; - class Image; - class IntRect; - - /** - * @internal - * - * a client who wants to load stylesheets, images or scripts from the web has to - * inherit from this class and overload one of the 3 functions - * - */ - class CachedResourceClient - { - public: - virtual ~CachedResourceClient() { } - - // Called whenever a frame of an image changes, either because we got more data from the network or - // because we are animating. - virtual void imageChanged(CachedImage*) { }; - - // Called to find out if this client wants to actually display the image. Used to tell when we - // can halt animation. Content nodes that hold image refs for example would not render the image, - // but RenderImages would (assuming they have visibility: visible and their render tree isn't hidden - // e.g., in the b/f cache or in a background tab). - virtual bool willRenderImage(CachedImage*) { return false; } - - virtual void setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const CachedCSSStyleSheet*) { } - virtual void setXSLStyleSheet(const String& /*URL*/, const String& /*sheet*/) { } - - virtual void fontLoaded(CachedFont*) {}; - -#if ENABLE(XBL) - virtual void setXBLDocument(const String& /*URL*/, XBL::XBLDocument*) { } -#endif - - virtual void notifyFinished(CachedResource*) { } - }; - -} - -#endif diff --git a/WebCore/loader/CachedResourceClientWalker.cpp b/WebCore/loader/CachedResourceClientWalker.cpp deleted file mode 100644 index 970b0e0..0000000 --- a/WebCore/loader/CachedResourceClientWalker.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - This file is part of the KDE libraries - - 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 Apple Computer, Inc. - - 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 "CachedResourceClientWalker.h" - -namespace WebCore { - -CachedResourceClientWalker::CachedResourceClientWalker(const HashCountedSet<CachedResourceClient*>& set) - : m_clientSet(set), m_clientVector(set.size()), m_index(0) -{ - typedef HashCountedSet<CachedResourceClient*>::const_iterator Iterator; - Iterator end = set.end(); - size_t clientIndex = 0; - for (Iterator current = set.begin(); current != end; ++current) - m_clientVector[clientIndex++] = current->first; -} - -CachedResourceClient* CachedResourceClientWalker::next() -{ - size_t size = m_clientVector.size(); - while (m_index < size) { - CachedResourceClient* next = m_clientVector[m_index++]; - if (m_clientSet.contains(next)) - return next; - } - - return 0; -} - -} diff --git a/WebCore/loader/CachedResourceClientWalker.h b/WebCore/loader/CachedResourceClientWalker.h deleted file mode 100644 index 0bf98e4..0000000 --- a/WebCore/loader/CachedResourceClientWalker.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedResourceClientWalker_h -#define CachedResourceClientWalker_h - -#include <wtf/HashCountedSet.h> -#include <wtf/Vector.h> - -namespace WebCore { - - class CachedResourceClient; - - // Call this "walker" instead of iterator so people won't expect Qt or STL-style iterator interface. - // Just keep calling next() on this. It's safe from deletions of items. - class CachedResourceClientWalker { - public: - CachedResourceClientWalker(const HashCountedSet<CachedResourceClient*>&); - CachedResourceClient* next(); - private: - const HashCountedSet<CachedResourceClient*>& m_clientSet; - Vector<CachedResourceClient*> m_clientVector; - size_t m_index; - }; - -} - -#endif diff --git a/WebCore/loader/CachedResourceHandle.cpp b/WebCore/loader/CachedResourceHandle.cpp deleted file mode 100644 index 871292c..0000000 --- a/WebCore/loader/CachedResourceHandle.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CachedResourceHandle.h" - -namespace WebCore { - -void CachedResourceHandleBase::setResource(CachedResource* resource) -{ - if (resource == m_resource) - return; - if (m_resource) - m_resource->unregisterHandle(this); - m_resource = resource; - if (m_resource) - m_resource->registerHandle(this); -} - -} diff --git a/WebCore/loader/CachedResourceHandle.h b/WebCore/loader/CachedResourceHandle.h deleted file mode 100644 index 13c03c7..0000000 --- a/WebCore/loader/CachedResourceHandle.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CachedResourceHandle_h -#define CachedResourceHandle_h - -#include "CachedResource.h" - -namespace WebCore { - - class CachedResourceHandleBase { - public: - ~CachedResourceHandleBase() { if (m_resource) m_resource->unregisterHandle(this); } - CachedResource* get() const { return m_resource; } - - bool operator!() const { return !m_resource; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef CachedResource* CachedResourceHandleBase::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_resource ? &CachedResourceHandleBase::m_resource : 0; } - - protected: - CachedResourceHandleBase() : m_resource(0) {} - CachedResourceHandleBase(CachedResource* res) { m_resource = res; if (m_resource) m_resource->registerHandle(this); } - CachedResourceHandleBase(const CachedResourceHandleBase& o) : m_resource(o.m_resource) { if (m_resource) m_resource->registerHandle(this); } - - void setResource(CachedResource*); - - private: - CachedResourceHandleBase& operator=(const CachedResourceHandleBase&) { return *this; } - - friend class CachedResource; - - CachedResource* m_resource; - }; - - template <class R> class CachedResourceHandle : public CachedResourceHandleBase { - public: - CachedResourceHandle() { } - CachedResourceHandle(R* res) : CachedResourceHandleBase(res) { } - CachedResourceHandle(const CachedResourceHandle<R>& o) : CachedResourceHandleBase(o) { } - - R* get() const { return reinterpret_cast<R*>(CachedResourceHandleBase::get()); } - R* operator->() const { return get(); } - - CachedResourceHandle& operator=(R* res) { setResource(res); return *this; } - CachedResourceHandle& operator=(const CachedResourceHandle& o) { setResource(o.get()); return *this; } - bool operator==(const CachedResourceHandleBase& o) const { return get() == o.get(); } - bool operator!=(const CachedResourceHandleBase& o) const { return get() != o.get(); } - }; - - template <class R, class RR> bool operator==(const CachedResourceHandle<R>& h, const RR* res) - { - return h.get() == res; - } - template <class R, class RR> bool operator==(const RR* res, const CachedResourceHandle<R>& h) - { - return h.get() == res; - } - template <class R, class RR> bool operator!=(const CachedResourceHandle<R>& h, const RR* res) - { - return h.get() != res; - } - template <class R, class RR> bool operator!=(const RR* res, const CachedResourceHandle<R>& h) - { - return h.get() != res; - } -} - -#endif diff --git a/WebCore/loader/CachedScript.cpp b/WebCore/loader/CachedScript.cpp deleted file mode 100644 index c8caea8..0000000 --- a/WebCore/loader/CachedScript.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - This file is part of the KDE libraries - - 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 Apple Computer, Inc. - - 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 "CachedScript.h" - -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include <wtf/Vector.h> - -namespace WebCore { - -CachedScript::CachedScript(const String& url, const String& charset) - : CachedResource(url, Script) - , m_encoding(charset) -{ - // It's javascript we want. - // But some websites think their scripts are <some wrong mimetype here> - // and refuse to serve them if we only accept application/x-javascript. - setAccept("*/*"); - if (!m_encoding.isValid()) - m_encoding = Latin1Encoding(); -} - -CachedScript::~CachedScript() -{ -} - -void CachedScript::addClient(CachedResourceClient* c) -{ - CachedResource::addClient(c); - if (!m_loading) - c->notifyFinished(this); -} - -void CachedScript::setEncoding(const String& chs) -{ - TextEncoding encoding(chs); - if (encoding.isValid()) - m_encoding = encoding; -} - -String CachedScript::encoding() const -{ - return m_encoding.name(); -} - -void CachedScript::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - if (m_data.get()) - m_script = m_encoding.decode(m_data->data(), encodedSize()); -#ifdef ANDROID_FIX // FIXME Newer webkit calls setDecodedSize in CachedScript::script(); remove on webkit update - // report decoded size too - setDecodedSize(m_script.length() * sizeof(UChar)); -#endif - m_loading = false; - checkNotify(); -} - -void CachedScript::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - -void CachedScript::error() -{ - m_loading = false; - m_errorOccurred = true; - checkNotify(); -} - -} diff --git a/WebCore/loader/CachedScript.h b/WebCore/loader/CachedScript.h deleted file mode 100644 index 4580cfe..0000000 --- a/WebCore/loader/CachedScript.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedScript_h -#define CachedScript_h - -#include "CachedResource.h" -#include "TextEncoding.h" - -namespace WebCore { - - class DocLoader; - - class CachedScript : public CachedResource { - public: - CachedScript(const String& url, const String& charset); - virtual ~CachedScript(); - - const String& script() const { return m_script; } - - virtual void addClient(CachedResourceClient*); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(); - - virtual bool schedule() const { return false; } - - void checkNotify(); - - private: - String m_script; - TextEncoding m_encoding; - }; -} - -#endif diff --git a/WebCore/loader/CachedXBLDocument.cpp b/WebCore/loader/CachedXBLDocument.cpp deleted file mode 100644 index 1ef3bae..0000000 --- a/WebCore/loader/CachedXBLDocument.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - This file is part of the KDE libraries - - 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 Apple Computer, Inc. - - 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" - -#if ENABLE(XBL) - -#include "CachedXBLDocument.h" - -#include "CachedResourceClientWalker.h" -#include "TextResourceDecoder.h" -#include <wtf/Vector.h> - -namespace WebCore { - -CachedXBLDocument::CachedXBLDocument(const String &url) -: CachedResource(url, XBL), m_document(0) -{ - // It's XML we want. - setAccept("text/xml, application/xml, application/xhtml+xml, text/xsl, application/rss+xml, application/atom+xml"); - - m_decoder = new TextResourceDecoder("application/xml"); -} - -CachedXBLDocument::~CachedXBLDocument() -{ - if (m_document) - m_document->deref(); -} - -void CachedXBLDocument::ref(CachedResourceClient *c) -{ - CachedResource::ref(c); - if (!m_loading) - c->setXBLDocument(m_url, m_document); -} - -void CachedXBLDocument::setEncoding(const String& chs) -{ - m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader); -} - -String CachedXBLDocument::encoding() const -{ - return m_decoder->encoding().name(); -} - -void CachedXBLDocument::data(Vector<char>& data, bool ) -{ - if (!allDataReceived) - return; - - ASSERT(!m_document); - - m_document = new XBL::XBLDocument(); - m_document->ref(); - m_document->open(); - - m_document->write(m_decoder->decode(data.data(), data.size())); - setSize(data.size()); - - m_document->finishParsing(); - m_document->close(); - m_loading = false; - checkNotify(); -} - -void CachedXBLDocument::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->setXBLDocument(m_url, m_document); -} - -void CachedXBLDocument::error() -{ - m_loading = false; - m_errorOccurred = true; - checkNotify(); -} - -} - -#endif diff --git a/WebCore/loader/CachedXBLDocument.h b/WebCore/loader/CachedXBLDocument.h deleted file mode 100644 index a66a0cb..0000000 --- a/WebCore/loader/CachedXBLDocument.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedXBLDocument_h -#define CachedXBLDocument_h - -#include "CachedResource.h" -#include <wtf/Vector.h> - -namespace WebCore { - class CachedResource; - class Request; - class DocLoader; - class TextResourceDecoder; - class CachedResourceClient; - -#if ENABLE(XBL) - class CachedXBLDocument : public CachedResource { - public: - CachedXBLDocument(const String& url); - virtual ~CachedXBLDocument(); - - XBL::XBLDocument* document() const { return m_document; } - - virtual void addClient(CachedResourceClient*); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(Vector<char>&, bool allDataReceived); - virtual void error(); - - virtual bool schedule() const { return true; } - - void checkNotify(); - - protected: - XBL::XBLDocument* m_document; - RefPtr<TextResourceDecoder> m_decoder; - }; - -#endif - -} - -#endif diff --git a/WebCore/loader/CachedXSLStyleSheet.cpp b/WebCore/loader/CachedXSLStyleSheet.cpp deleted file mode 100644 index 009b2af..0000000 --- a/WebCore/loader/CachedXSLStyleSheet.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - This file is part of the KDE libraries - - 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 Apple Computer, Inc. - - 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 "CachedXSLStyleSheet.h" - -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "TextResourceDecoder.h" -#include <wtf/Vector.h> - -namespace WebCore { - -#if ENABLE(XSLT) - -CachedXSLStyleSheet::CachedXSLStyleSheet(const String &url) - : CachedResource(url, XSLStyleSheet) - , m_decoder(TextResourceDecoder::create("text/xsl")) -{ - // It's XML we want. - // FIXME: This should accept more general xml formats */*+xml, image/svg+xml for example. - setAccept("text/xml, application/xml, application/xhtml+xml, text/xsl, application/rss+xml, application/atom+xml"); -} - -void CachedXSLStyleSheet::addClient(CachedResourceClient *c) -{ - CachedResource::addClient(c); - - if (!m_loading) - c->setXSLStyleSheet(m_url, m_sheet); -} - -void CachedXSLStyleSheet::setEncoding(const String& chs) -{ - m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader); -} - -String CachedXSLStyleSheet::encoding() const -{ - return m_decoder->encoding().name(); -} - -void CachedXSLStyleSheet::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - if (m_data.get()) { - m_sheet = String(m_decoder->decode(m_data->data(), encodedSize())); - m_sheet += m_decoder->flush(); - } - m_loading = false; - checkNotify(); -} - -void CachedXSLStyleSheet::checkNotify() -{ - if (m_loading) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->setXSLStyleSheet(m_url, m_sheet); -} - - -void CachedXSLStyleSheet::error() -{ - m_loading = false; - m_errorOccurred = true; - checkNotify(); -} - -#endif - -} diff --git a/WebCore/loader/CachedXSLStyleSheet.h b/WebCore/loader/CachedXSLStyleSheet.h deleted file mode 100644 index c5326fa..0000000 --- a/WebCore/loader/CachedXSLStyleSheet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of the KDE libraries - - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef CachedXSLStyleSheet_h -#define CachedXSLStyleSheet_h - -#include "CachedResource.h" -#include <wtf/Vector.h> - -namespace WebCore { - - class DocLoader; - class TextResourceDecoder; - -#if ENABLE(XSLT) - class CachedXSLStyleSheet : public CachedResource { - public: - CachedXSLStyleSheet(const String& url); - - const String& sheet() const { return m_sheet; } - - virtual void addClient(CachedResourceClient*); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(); - - virtual bool schedule() const { return true; } - - void checkNotify(); - - protected: - String m_sheet; - RefPtr<TextResourceDecoder> m_decoder; - }; - -#endif - -} - -#endif diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp deleted file mode 100644 index 4dbc6a0..0000000 --- a/WebCore/loader/DocLoader.cpp +++ /dev/null @@ -1,468 +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. - - 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 0 - -namespace WebCore { - -DocLoader::DocLoader(Document* doc) - : m_cache(cache()) - , m_cachePolicy(CachePolicyVerify) - , 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() -{ - clearPreloads(); - HashMap<String, CachedResource*>::iterator end = m_docResources.end(); - for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) - it->second->setDocLoader(0); - m_cache->removeDocLoader(this); -} - -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_cachePolicy == CachePolicyVerify || m_cachePolicy == CachePolicyCache) { - if (!m_reloadedURLs.contains(fullURL.string())) { - CachedResource* existing = cache()->resourceForURL(fullURL.string()); - if (existing && !existing->isPreloaded() && existing->mustRevalidate(m_cachePolicy)) { - cache()->revalidateResource(existing, this); - m_reloadedURLs.add(fullURL.string()); - } - } - } else if ((m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)) { - if (!m_reloadedURLs.contains(fullURL.string())) { - CachedResource* existing = cache()->resourceForURL(fullURL.string()); - if (existing && !existing->isPreloaded()) { - // FIXME: Use revalidateResource() to implement HTTP 1.1 "Specific end-to-end revalidation" for regular reloading - cache()->remove(existing); - 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()) { -#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(XBL) -CachedXBLDocument* DocLoader::requestXBLDocument(const String& url) -{ - return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XBL, 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: - // 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 (!canRequest(type, fullURL)) - return 0; - - if (cache()->disabled()) { - HashMap<String, CachedResource*>::iterator it = m_docResources.find(fullURL.string()); - - if (it != m_docResources.end()) { - it->second->setDocLoader(0); - m_docResources.remove(it); - } - } - - if (frame() && frame()->loader()->isReloading()) - setCachePolicy(CachePolicyReload); - - 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_docResources.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; - - HashMap<String, CachedResource*>::iterator end = m_docResources.end(); - for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) { - CachedResource* resource = it->second; - 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(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; - - HashMap<String, CachedResource*>::iterator end = m_docResources.end(); - for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) { - CachedResource* resource = it->second; - 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 - -void DocLoader::setCachePolicy(CachePolicy cachePolicy) -{ - m_cachePolicy = cachePolicy; -} - -void DocLoader::removeCachedResource(CachedResource* resource) const -{ - m_docResources.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(); -} - -#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 - -} diff --git a/WebCore/loader/DocLoader.h b/WebCore/loader/DocLoader.h deleted file mode 100644 index 407d85a..0000000 --- a/WebCore/loader/DocLoader.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#ifndef DocLoader_h -#define DocLoader_h - -#include "CachedResource.h" -#include "CachePolicy.h" -#include "StringHash.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/ListHashSet.h> - -namespace WebCore { - -class CachedCSSStyleSheet; -class CachedFont; -class CachedImage; -class CachedScript; -class CachedXSLStyleSheet; -class Document; -class Frame; -class ImageLoader; -class KURL; - -// The DocLoader manages the loading of scripts/images/stylesheets for a single document. -class DocLoader -{ -friend class Cache; -friend class ImageLoader; - -public: - DocLoader(Document*); - ~DocLoader(); - - CachedImage* requestImage(const String& url); - CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset); - CachedCSSStyleSheet* requestUserCSSStyleSheet(const String& url, const String& charset); - CachedScript* requestScript(const String& url, const String& charset); - CachedFont* requestFont(const String& url); - -#if ENABLE(XSLT) - CachedXSLStyleSheet* requestXSLStyleSheet(const String& url); -#endif -#if ENABLE(XBL) - CachedXBLDocument* requestXBLDocument(const String &url); -#endif - - // Logs an access denied message to the console for the specified URL. - void printAccessDeniedMessage(const KURL& url) const; - - CachedResource* cachedResource(const String& url) const { return m_docResources.get(url); } - const HashMap<String, CachedResource*>& allCachedResources() const { return m_docResources; } - - bool autoLoadImages() const { return m_autoLoadImages; } - void setAutoLoadImages(bool); - -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - bool blockNetworkImage() const { return m_blockNetworkImage; } - void setBlockNetworkImage(bool); - bool shouldBlockNetworkImage(const String& url) const; -#endif - - CachePolicy cachePolicy() const { return m_cachePolicy; } - void setCachePolicy(CachePolicy); - - Frame* frame() const; // Can be NULL - Document* doc() const { return m_doc; } - - void removeCachedResource(CachedResource*) const; - - void setLoadInProgress(bool); - bool loadInProgress() const { return m_loadInProgress; } - - void setAllowStaleResources(bool allowStaleResources) { m_allowStaleResources = allowStaleResources; } - -#if USE(LOW_BANDWIDTH_DISPLAY) - void replaceDocument(Document* doc) { m_doc = doc; } -#endif - - void incrementRequestCount(); - void decrementRequestCount(); - int requestCount(); - - void clearPreloads(); - void preload(CachedResource::Type, const String& url, const String& charset, bool referencedFromBody); - void checkForPendingPreloads(); - void printPreloadStats(); - -private: - CachedResource* requestResource(CachedResource::Type, const String& url, const String& charset, bool isPreload = false); - void requestPreload(CachedResource::Type, const String& url, const String& charset); - - void checkForReload(const KURL&); - void checkCacheObjectStatus(CachedResource*); - bool canRequest(CachedResource::Type, const KURL&); - - Cache* m_cache; - HashSet<String> m_reloadedURLs; - mutable HashMap<String, CachedResource*> m_docResources; - CachePolicy m_cachePolicy; - Document* m_doc; - - int m_requestCount; - - ListHashSet<CachedResource*> m_preloads; - struct PendingPreload { - CachedResource::Type m_type; - String m_url; - String m_charset; - }; - Vector<PendingPreload> m_pendingPreloads; - - //29 bits left -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - bool m_blockNetworkImage : 1; -#endif - bool m_autoLoadImages : 1; - bool m_loadInProgress : 1; - bool m_allowStaleResources : 1; -}; - -} - -#endif diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp deleted file mode 100644 index d9d99ea..0000000 --- a/WebCore/loader/DocumentLoader.cpp +++ /dev/null @@ -1,924 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DocumentLoader.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) -#include "ApplicationCache.h" -#include "ApplicationCacheGroup.h" -#include "ApplicationCacheResource.h" -#endif -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -#include "ArchiveFactory.h" -#include "ArchiveResourceCollection.h" -#else -#include "SubstituteResource.h" -#endif -#include "CachedPage.h" -#include "DocLoader.h" -#include "Document.h" -#include "Event.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameTree.h" -#include "HistoryItem.h" -#include "Logging.h" -#include "MainResourceLoader.h" -#include "Page.h" -#include "PlatformString.h" -#include "Settings.h" -#include "SharedBuffer.h" -#include "StringBuffer.h" -#include "XMLTokenizer.h" - -#include <wtf/Assertions.h> -#include <wtf/unicode/Unicode.h> - -namespace WebCore { - -/* - * Performs four operations: - * 1. Convert backslashes to currency symbols - * 2. Convert control characters to spaces - * 3. Trim leading and trailing spaces - * 4. Collapse internal whitespace. - */ -static inline String canonicalizedTitle(const String& title, Frame* frame) -{ - ASSERT(!title.isEmpty()); - - const UChar* characters = title.characters(); - unsigned length = title.length(); - unsigned i; - - StringBuffer buffer(length); - unsigned builderIndex = 0; - - // Skip leading spaces and leading characters that would convert to spaces - for (i = 0; i < length; ++i) { - UChar c = characters[i]; - if (!(c <= 0x20 || c == 0x7F)) - break; - } - - if (i == length) - return ""; - - // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace. - bool previousCharWasWS = false; - for (; i < length; ++i) { - UChar c = characters[i]; - if (c <= 0x20 || c == 0x7F || (WTF::Unicode::category(c) & (WTF::Unicode::Separator_Line | WTF::Unicode::Separator_Paragraph))) { - if (previousCharWasWS) - continue; - buffer[builderIndex++] = ' '; - previousCharWasWS = true; - } else if (c == '\\') { - buffer[builderIndex++] = frame->backslashAsCurrencySymbol(); - previousCharWasWS = false; - } else { - buffer[builderIndex++] = c; - previousCharWasWS = false; - } - } - - // Strip trailing spaces - while (builderIndex > 0) { - --builderIndex; - if (buffer[builderIndex] != ' ') - break; - } - - if (!builderIndex && buffer[builderIndex] == ' ') - return ""; - - buffer.shrink(builderIndex + 1); - return String::adopt(buffer); -} - -static void cancelAll(const ResourceLoaderSet& loaders) -{ - const ResourceLoaderSet copy = loaders; - ResourceLoaderSet::const_iterator end = copy.end(); - for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it) - (*it)->cancel(); -} - -static void setAllDefersLoading(const ResourceLoaderSet& loaders, bool defers) -{ - const ResourceLoaderSet copy = loaders; - ResourceLoaderSet::const_iterator end = copy.end(); - for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it) - (*it)->setDefersLoading(defers); -} - -DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData& substituteData) - : m_deferMainResourceDataLoad(true) - , m_frame(0) - , m_originalRequest(req) - , m_substituteData(substituteData) - , m_originalRequestCopy(req) - , m_request(req) - , m_committed(false) - , m_isStopping(false) - , m_loading(false) - , m_gotFirstByte(false) - , m_primaryLoadComplete(false) - , m_isClientRedirect(false) - , m_loadingFromCachedPage(false) - , m_stopRecordingResponses(false) - , m_substituteResourceDeliveryTimer(this, &DocumentLoader::substituteResourceDeliveryTimerFired) -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - , m_candidateApplicationCacheGroup(0) -#endif -{ -} - -FrameLoader* DocumentLoader::frameLoader() const -{ - if (!m_frame) - return 0; - return m_frame->loader(); -} - -DocumentLoader::~DocumentLoader() -{ - ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !frameLoader()->isLoading()); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (m_applicationCache) - m_applicationCache->group()->documentLoaderDestroyed(this); - else if (m_candidateApplicationCacheGroup) - m_candidateApplicationCacheGroup->documentLoaderDestroyed(this); -#endif -} - -PassRefPtr<SharedBuffer> DocumentLoader::mainResourceData() const -{ - if (m_mainResourceData) - return m_mainResourceData; - if (m_mainResourceLoader) - return m_mainResourceLoader->resourceData(); - return 0; -} - -const ResourceRequest& DocumentLoader::originalRequest() const -{ - return m_originalRequest; -} - -const ResourceRequest& DocumentLoader::originalRequestCopy() const -{ - return m_originalRequestCopy; -} - -const ResourceRequest& DocumentLoader::request() const -{ - return m_request; -} - -ResourceRequest& DocumentLoader::request() -{ - return m_request; -} - -const KURL& DocumentLoader::url() const -{ - return request().url(); -} - -void DocumentLoader::replaceRequestURLForAnchorScroll(const KURL& url) -{ - m_originalRequestCopy.setURL(url); - m_request.setURL(url); -} - -void DocumentLoader::setRequest(const ResourceRequest& req) -{ - // Replacing an unreachable URL with alternate content looks like a server-side - // redirect at this point, but we can replace a committed dataSource. - bool handlingUnreachableURL = false; - - handlingUnreachableURL = m_substituteData.isValid() && !m_substituteData.failingURL().isEmpty(); - - if (handlingUnreachableURL) - m_committed = false; - - // We should never be getting a redirect callback after the data - // source is committed, except in the unreachable URL case. It - // would be a WebFoundation bug if it sent a redirect callback after commit. - ASSERT(!m_committed); - - KURL oldURL = m_request.url(); - m_request = req; - - // Only send webView:didReceiveServerRedirectForProvisionalLoadForFrame: if URL changed. - // Also, don't send it when replacing unreachable URLs with alternate content. - if (!handlingUnreachableURL && oldURL != req.url()) - frameLoader()->didReceiveServerRedirectForProvisionalLoadForFrame(); -} - -void DocumentLoader::setMainDocumentError(const ResourceError& error) -{ - m_mainDocumentError = error; - frameLoader()->setMainDocumentError(this, error); - } - -void DocumentLoader::clearErrors() -{ - m_mainDocumentError = ResourceError(); -} - -void DocumentLoader::mainReceivedError(const ResourceError& error, bool isComplete) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - ApplicationCacheGroup* group = m_candidateApplicationCacheGroup; - if (!group && m_applicationCache && !mainResourceApplicationCache()) - group = m_applicationCache->group(); - - if (group) - group->failedLoadingMainResource(this); -#endif - - if (!frameLoader()) - return; - setMainDocumentError(error); - if (isComplete) - frameLoader()->mainReceivedCompleteError(this, error); -} - -// Cancels the data source's pending loads. Conceptually, a data source only loads -// one document at a time, but one document may have many related resources. -// stopLoading will stop all loads initiated by the data source, -// but not loads initiated by child frames' data sources -- that's the WebFrame's job. -void DocumentLoader::stopLoading() -{ - // In some rare cases, calling FrameLoader::stopLoading could set m_loading to false. - // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it - // to stop loading. Because of this, we need to save it so we don't return early. - bool loading = m_loading; - - if (m_committed) { - // Attempt to stop the frame if the document loader is loading, or if it is done loading but - // still parsing. Failure to do so can cause a world leak. - Document* doc = m_frame->document(); - - if (loading || (doc && doc->parsing())) - m_frame->loader()->stopLoading(false); - } - - // Always cancel multipart loaders - cancelAll(m_multipartSubresourceLoaders); - - if (!loading) - return; - - RefPtr<Frame> protectFrame(m_frame); - RefPtr<DocumentLoader> protectLoader(this); - - m_isStopping = true; - - FrameLoader* frameLoader = DocumentLoader::frameLoader(); - - if (m_mainResourceLoader) - // Stop the main resource loader and let it send the cancelled message. - m_mainResourceLoader->cancel(); - else if (!m_subresourceLoaders.isEmpty()) - // The main resource loader already finished loading. Set the cancelled error on the - // document and let the subresourceLoaders send individual cancelled messages below. - setMainDocumentError(frameLoader->cancelledError(m_request)); - else - // If there are no resource loaders, we need to manufacture a cancelled message. - // (A back/forward navigation has no resource loaders because its resources are cached.) - mainReceivedError(frameLoader->cancelledError(m_request), true); - - stopLoadingSubresources(); - stopLoadingPlugIns(); - - m_isStopping = false; -} - -void DocumentLoader::setupForReplace() -{ - frameLoader()->setupForReplace(); - m_committed = false; -} - -void DocumentLoader::commitIfReady() -{ - if (m_gotFirstByte && !m_committed) { - m_committed = true; - frameLoader()->commitProvisionalLoad(0); - } -} - -void DocumentLoader::finishedLoading() -{ - m_gotFirstByte = true; - commitIfReady(); - if (FrameLoader* loader = frameLoader()) { - loader->finishedLoadingDocument(this); - loader->end(); - } -} - -void DocumentLoader::commitLoad(const char* data, int length) -{ - // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource - // by starting a new load, so retain temporarily. - RefPtr<DocumentLoader> protect(this); - - commitIfReady(); - if (FrameLoader* frameLoader = DocumentLoader::frameLoader()) - frameLoader->committedLoad(this, data, length); -} - -bool DocumentLoader::doesProgressiveLoad(const String& MIMEType) const -{ - return !frameLoader()->isReplacing() || MIMEType == "text/html"; -} - -void DocumentLoader::receivedData(const char* data, int length) -{ - m_gotFirstByte = true; - if (doesProgressiveLoad(m_response.mimeType())) - commitLoad(data, length); -} - -void DocumentLoader::setupForReplaceByMIMEType(const String& newMIMEType) -{ - if (!m_gotFirstByte) - return; - - String oldMIMEType = m_response.mimeType(); - - if (!doesProgressiveLoad(oldMIMEType)) { - frameLoader()->revertToProvisional(this); - setupForReplace(); - RefPtr<SharedBuffer> resourceData = mainResourceData(); - commitLoad(resourceData->data(), resourceData->size()); - } - - frameLoader()->finishedLoadingDocument(this); - m_frame->loader()->end(); - - frameLoader()->setReplacing(); - m_gotFirstByte = false; - - if (doesProgressiveLoad(newMIMEType)) { - frameLoader()->revertToProvisional(this); - setupForReplace(); - } - - stopLoadingSubresources(); - stopLoadingPlugIns(); -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - clearArchiveResources(); -#endif -} - -void DocumentLoader::updateLoading() -{ - ASSERT(this == frameLoader()->activeDocumentLoader()); - setLoading(frameLoader()->isLoading()); -} - -void DocumentLoader::setFrame(Frame* frame) -{ - if (m_frame == frame) - return; - ASSERT(frame && !m_frame); - m_frame = frame; - attachToFrame(); -} - -void DocumentLoader::attachToFrame() -{ - ASSERT(m_frame); -} - -void DocumentLoader::detachFromFrame() -{ - ASSERT(m_frame); - m_frame = 0; -} - -void DocumentLoader::prepareForLoadStart() -{ - ASSERT(!m_isStopping); - setPrimaryLoadComplete(false); - ASSERT(frameLoader()); - clearErrors(); - - setLoading(true); - - frameLoader()->prepareForLoadStart(); -} - -void DocumentLoader::setPrimaryLoadComplete(bool flag) -{ - m_primaryLoadComplete = flag; - if (flag) { - if (m_mainResourceLoader) { - m_mainResourceData = m_mainResourceLoader->resourceData(); -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - m_mainResourceApplicationCache = m_mainResourceLoader->applicationCache(); -#endif - m_mainResourceLoader = 0; - } - updateLoading(); - } -} - -bool DocumentLoader::isLoadingInAPISense() const -{ - // Once a frame has loaded, we no longer need to consider subresources, - // but we still need to consider subframes. - if (frameLoader()->state() != FrameStateComplete) { - if (!m_primaryLoadComplete && isLoading()) - return true; - if (!m_subresourceLoaders.isEmpty()) - return true; - if (Document* doc = m_frame->document()) { - if (doc->docLoader()->requestCount()) - return true; - if (Tokenizer* tok = doc->tokenizer()) - if (tok->processingData()) - return true; - } - } - return frameLoader()->subframeIsLoading(); -} - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -void DocumentLoader::addAllArchiveResources(Archive* archive) -{ - if (!m_archiveResourceCollection) - m_archiveResourceCollection.set(new ArchiveResourceCollection); - - ASSERT(archive); - if (!archive) - return; - - m_archiveResourceCollection->addAllResources(archive); -} - -// FIXME: Adding a resource directly to a DocumentLoader/ArchiveResourceCollection seems like bad design, but is API some apps rely on. -// Can we change the design in a manner that will let us deprecate that API without reducing functionality of those apps? -void DocumentLoader::addArchiveResource(PassRefPtr<ArchiveResource> resource) -{ - if (!m_archiveResourceCollection) - m_archiveResourceCollection.set(new ArchiveResourceCollection); - - ASSERT(resource); - if (!resource) - return; - - m_archiveResourceCollection->addResource(resource); -} - -ArchiveResource* DocumentLoader::archiveResourceForURL(const KURL& url) const -{ - if (!m_archiveResourceCollection) - return 0; - - ArchiveResource* resource = m_archiveResourceCollection->archiveResourceForURL(url); - - return resource && !resource->shouldIgnoreWhenUnarchiving() ? resource : 0; -} - -PassRefPtr<Archive> DocumentLoader::popArchiveForSubframe(const String& frameName) -{ - return m_archiveResourceCollection ? m_archiveResourceCollection->popSubframeArchive(frameName) : 0; -} - -void DocumentLoader::clearArchiveResources() -{ - m_archiveResourceCollection.clear(); - m_substituteResourceDeliveryTimer.stop(); -} - -void DocumentLoader::setParsedArchiveData(PassRefPtr<SharedBuffer> data) -{ - m_parsedArchiveData = data; -} - -SharedBuffer* DocumentLoader::parsedArchiveData() const -{ - return m_parsedArchiveData.get(); -} - -PassRefPtr<ArchiveResource> DocumentLoader::mainResource() const -{ - const ResourceResponse& r = response(); - RefPtr<SharedBuffer> mainResourceBuffer = mainResourceData(); - if (!mainResourceBuffer) - mainResourceBuffer = SharedBuffer::create(); - - return ArchiveResource::create(mainResourceBuffer, r.url(), r.mimeType(), r.textEncodingName(), frame()->tree()->name()); -} - -PassRefPtr<ArchiveResource> DocumentLoader::subresource(const KURL& url) const -{ - if (!isCommitted()) - return 0; - - Document* doc = m_frame->document(); - if (!doc) - return archiveResourceForURL(url); - - CachedResource* resource = doc->docLoader()->cachedResource(url); - if (!resource || resource->preloadResult() == CachedResource::PreloadReferenced) - return archiveResourceForURL(url); - - return ArchiveResource::create(resource->data(), url, resource->response()); -} - -void DocumentLoader::getSubresources(Vector<PassRefPtr<ArchiveResource> >& subresources) const -{ - if (!isCommitted()) - return; - - Document* document = m_frame->document(); - if (!document) - return; - - const HashMap<String, CachedResource*>& allResources = document->docLoader()->allCachedResources(); - HashMap<String, CachedResource*>::const_iterator end = allResources.end(); - for (HashMap<String, CachedResource*>::const_iterator it = allResources.begin(); it != end; ++it) { - RefPtr<ArchiveResource> subresource = this->subresource(KURL(it->second->url())); - if (subresource) - subresources.append(subresource.release()); - } - - return; -} -#endif - -void DocumentLoader::deliverSubstituteResourcesAfterDelay() -{ - if (m_pendingSubstituteResources.isEmpty()) - return; - ASSERT(m_frame && m_frame->page()); - if (m_frame->page()->defersLoading()) - return; - if (!m_substituteResourceDeliveryTimer.isActive()) - m_substituteResourceDeliveryTimer.startOneShot(0); -} - -void DocumentLoader::substituteResourceDeliveryTimerFired(Timer<DocumentLoader>*) -{ - if (m_pendingSubstituteResources.isEmpty()) - return; - ASSERT(m_frame && m_frame->page()); - if (m_frame->page()->defersLoading()) - return; - - SubstituteResourceMap copy; - copy.swap(m_pendingSubstituteResources); - - SubstituteResourceMap::const_iterator end = copy.end(); - for (SubstituteResourceMap::const_iterator it = copy.begin(); it != end; ++it) { - RefPtr<ResourceLoader> loader = it->first; - SubstituteResource* resource = it->second.get(); - - if (resource) { - SharedBuffer* data = resource->data(); - - loader->didReceiveResponse(resource->response()); - loader->didReceiveData(data->data(), data->size(), data->size(), true); - loader->didFinishLoading(); - } else { - // A null resource means that we should fail the load. - // FIXME: Maybe we should use another error here - something like "not in cache". - loader->didFail(loader->cannotShowURLError()); - } - } -} - -#ifndef NDEBUG -bool DocumentLoader::isSubstituteLoadPending(ResourceLoader* loader) const -{ - return m_pendingSubstituteResources.contains(loader); -} -#endif - -void DocumentLoader::cancelPendingSubstituteLoad(ResourceLoader* loader) -{ - if (m_pendingSubstituteResources.isEmpty()) - return; - m_pendingSubstituteResources.remove(loader); - if (m_pendingSubstituteResources.isEmpty()) - m_substituteResourceDeliveryTimer.stop(); -} - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -bool DocumentLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) -{ - ArchiveResource* resource = 0; - - if (request.url() == originalURL) - resource = archiveResourceForURL(originalURL); - - if (!resource) { - // WebArchiveDebugMode means we fail loads instead of trying to fetch them from the network if they're not in the archive. - bool shouldFailLoad = m_frame->settings()->webArchiveDebugModeEnabled() && ArchiveFactory::isArchiveMimeType(responseMIMEType()); - - if (!shouldFailLoad) - return false; - } - - m_pendingSubstituteResources.set(loader, resource); - deliverSubstituteResourcesAfterDelay(); - - return true; -} -#endif - -void DocumentLoader::addResponse(const ResourceResponse& r) -{ - if (!m_stopRecordingResponses) - m_responses.append(r); -} - -void DocumentLoader::stopRecordingResponses() -{ - m_stopRecordingResponses = true; -} - -void DocumentLoader::setTitle(const String& title) -{ - if (title.isEmpty()) - return; - - String trimmed = canonicalizedTitle(title, m_frame); - if (!trimmed.isEmpty() && m_pageTitle != trimmed) { - frameLoader()->willChangeTitle(this); - m_pageTitle = trimmed; - frameLoader()->didChangeTitle(this); - } -} - -KURL DocumentLoader::urlForHistory() const -{ - // Return the URL to be used for history and B/F list. - // Returns nil for WebDataProtocol URLs that aren't alternates - // for unreachable URLs, because these can't be stored in history. - if (m_substituteData.isValid()) - return unreachableURL(); - - return m_originalRequestCopy.url(); -} - -void DocumentLoader::loadFromCachedPage(PassRefPtr<CachedPage> cachedPage) -{ - LOG(PageCache, "WebCorePageCache: DocumentLoader %p loading from cached page %p", this, cachedPage.get()); - - prepareForLoadStart(); - setLoadingFromCachedPage(true); - setCommitted(true); - frameLoader()->commitProvisionalLoad(cachedPage); -} - -const KURL& DocumentLoader::originalURL() const -{ - return m_originalRequestCopy.url(); -} - -const KURL& DocumentLoader::requestURL() const -{ - return request().url(); -} - -const KURL& DocumentLoader::responseURL() const -{ - return m_response.url(); -} - -const String& DocumentLoader::responseMIMEType() const -{ - return m_response.mimeType(); -} - -const KURL& DocumentLoader::unreachableURL() const -{ - return m_substituteData.failingURL(); -} - -void DocumentLoader::setDefersLoading(bool defers) -{ - if (m_mainResourceLoader) - m_mainResourceLoader->setDefersLoading(defers); - setAllDefersLoading(m_subresourceLoaders, defers); - setAllDefersLoading(m_plugInStreamLoaders, defers); - if (!defers) - deliverSubstituteResourcesAfterDelay(); -} - -void DocumentLoader::stopLoadingPlugIns() -{ - cancelAll(m_plugInStreamLoaders); -} - -void DocumentLoader::stopLoadingSubresources() -{ - cancelAll(m_subresourceLoaders); -} - -void DocumentLoader::addSubresourceLoader(ResourceLoader* loader) -{ - m_subresourceLoaders.add(loader); - setLoading(true); -} - -void DocumentLoader::removeSubresourceLoader(ResourceLoader* loader) -{ - m_subresourceLoaders.remove(loader); - updateLoading(); - if (Frame* frame = m_frame) - frame->loader()->checkLoadComplete(); -} - -void DocumentLoader::addPlugInStreamLoader(ResourceLoader* loader) -{ - m_plugInStreamLoaders.add(loader); - setLoading(true); -} - -void DocumentLoader::removePlugInStreamLoader(ResourceLoader* loader) -{ - m_plugInStreamLoaders.remove(loader); - updateLoading(); -} - -bool DocumentLoader::isLoadingMainResource() const -{ - return !!m_mainResourceLoader; -} - -bool DocumentLoader::isLoadingSubresources() const -{ - return !m_subresourceLoaders.isEmpty(); -} - -bool DocumentLoader::isLoadingPlugIns() const -{ - return !m_plugInStreamLoaders.isEmpty(); -} - -bool DocumentLoader::isLoadingMultipartContent() const -{ - return m_mainResourceLoader && m_mainResourceLoader->isLoadingMultipartContent(); -} - -bool DocumentLoader::startLoadingMainResource(unsigned long identifier) -{ - ASSERT(!m_mainResourceLoader); - m_mainResourceLoader = MainResourceLoader::create(m_frame); - m_mainResourceLoader->setIdentifier(identifier); - - // FIXME: Is there any way the extra fields could have not been added by now? - // If not, it would be great to remove this line of code. - frameLoader()->addExtraFieldsToRequest(m_request, true, false); - - if (!m_mainResourceLoader->load(m_request, m_substituteData)) { - // FIXME: If this should really be caught, we should just ASSERT this doesn't happen; - // should it be caught by other parts of WebKit or other parts of the app? - LOG_ERROR("could not create WebResourceHandle for URL %s -- should be caught by policy handler level", m_request.url().string().ascii().data()); - m_mainResourceLoader = 0; - return false; - } - - return true; -} - -void DocumentLoader::cancelMainResourceLoad(const ResourceError& error) -{ - m_mainResourceLoader->cancel(error); -} - -void DocumentLoader::subresourceLoaderFinishedLoadingOnePart(ResourceLoader* loader) -{ - m_multipartSubresourceLoaders.add(loader); - m_subresourceLoaders.remove(loader); - updateLoading(); - if (Frame* frame = m_frame) - frame->loader()->checkLoadComplete(); -} - -void DocumentLoader::iconLoadDecisionAvailable() -{ - if (m_frame) - m_frame->loader()->iconLoadDecisionAvailable(); -} - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) -void DocumentLoader::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group) -{ - ASSERT(!m_applicationCache); - m_candidateApplicationCacheGroup = group; -} - -void DocumentLoader::setApplicationCache(PassRefPtr<ApplicationCache> applicationCache) -{ - if (m_candidateApplicationCacheGroup) { - ASSERT(!m_applicationCache); - m_candidateApplicationCacheGroup = 0; - } - - m_applicationCache = applicationCache; -} - -ApplicationCache* DocumentLoader::topLevelApplicationCache() const -{ - if (!m_frame) - return 0; - - if (m_applicationCache) - return m_applicationCache.get(); - - if (Page* page = m_frame->page()) - return page->mainFrame()->loader()->documentLoader()->applicationCache(); - - return 0; -} - -ApplicationCache* DocumentLoader::mainResourceApplicationCache() const -{ - if (m_mainResourceApplicationCache) - return m_mainResourceApplicationCache.get(); - if (m_mainResourceLoader) - return m_mainResourceLoader->applicationCache(); - return 0; -} - -bool DocumentLoader::shouldLoadResourceFromApplicationCache(const ResourceRequest& request, ApplicationCacheResource*& resource) -{ - ApplicationCache* cache = topLevelApplicationCache(); - if (!cache) - return false; - - // If the resource is not a HTTP/HTTPS GET, then abort - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) - return false; - - if (cache->isURLInOnlineWhitelist(request.url())) - return false; - - resource = cache->resourceForURL(request.url()); - - // Don't load foreign resources. - if (resource && (resource->type() & ApplicationCacheResource::Foreign)) - resource = 0; - - return true; -} - -bool DocumentLoader::scheduleApplicationCacheLoad(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) -{ - if (!frameLoader()->frame()->settings() || !frameLoader()->frame()->settings()->offlineWebApplicationCacheEnabled()) - return false; - - if (request.url() != originalURL) - return false; - - ApplicationCacheResource* resource; - if (!shouldLoadResourceFromApplicationCache(request, resource)) - // FIXME: Handle opportunistic caching namespaces - return false; - - m_pendingSubstituteResources.set(loader, resource); - deliverSubstituteResourcesAfterDelay(); - - return true; -} - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -} diff --git a/WebCore/loader/DocumentLoader.h b/WebCore/loader/DocumentLoader.h deleted file mode 100644 index aef4f49..0000000 --- a/WebCore/loader/DocumentLoader.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DocumentLoader_h -#define DocumentLoader_h - -#include "IconDatabase.h" -#include "NavigationAction.h" -#include <wtf/RefCounted.h> -#include "PlatformString.h" -#include "ResourceError.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "SubstituteData.h" -#include <wtf/HashSet.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - class ApplicationCache; - class ApplicationCacheGroup; - class ApplicationCacheResource; -#endif -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - class Archive; - class ArchiveResource; - class ArchiveResourceCollection; -#endif - class CachedPage; - class Frame; - class FrameLoader; - class HistoryItem; - class KURL; - class MainResourceLoader; - class ResourceLoader; - class SchedulePair; - class SharedBuffer; - class SubstituteData; - class SubstituteResource; - - typedef HashSet<RefPtr<ResourceLoader> > ResourceLoaderSet; - typedef Vector<ResourceResponse> ResponseVector; - - class DocumentLoader : public RefCounted<DocumentLoader> { - public: - static PassRefPtr<DocumentLoader> create(const ResourceRequest& request, const SubstituteData& data) - { - return adoptRef(new DocumentLoader(request, data)); - } - virtual ~DocumentLoader(); - - void setFrame(Frame*); - Frame* frame() const { return m_frame; } - - virtual void attachToFrame(); - virtual void detachFromFrame(); - - FrameLoader* frameLoader() const; - MainResourceLoader* mainResourceLoader() const { return m_mainResourceLoader.get(); } - PassRefPtr<SharedBuffer> mainResourceData() const; - - const ResourceRequest& originalRequest() const; - const ResourceRequest& originalRequestCopy() const; - - const ResourceRequest& request() const; - ResourceRequest& request(); - void setRequest(const ResourceRequest&); - - const SubstituteData& substituteData() const { return m_substituteData; } - - const KURL& url() const; - const KURL& unreachableURL() const; - - const KURL& originalURL() const; - const KURL& requestURL() const; - const KURL& responseURL() const; - const String& responseMIMEType() const; - - void replaceRequestURLForAnchorScroll(const KURL&); - bool isStopping() const { return m_isStopping; } - void stopLoading(); - void setCommitted(bool committed) { m_committed = committed; } - bool isCommitted() const { return m_committed; } - bool isLoading() const { return m_loading; } - void setLoading(bool loading) { m_loading = loading; } - void updateLoading(); - void receivedData(const char*, int); - void setupForReplaceByMIMEType(const String& newMIMEType); - void finishedLoading(); - const ResourceResponse& response() const { return m_response; } - const ResourceError& mainDocumentError() const { return m_mainDocumentError; } - void mainReceivedError(const ResourceError&, bool isComplete); - void setResponse(const ResourceResponse& response) { m_response = response; } - void prepareForLoadStart(); - bool isClientRedirect() const { return m_isClientRedirect; } - void setIsClientRedirect(bool isClientRedirect) { m_isClientRedirect = isClientRedirect; } - bool isLoadingInAPISense() const; - void setPrimaryLoadComplete(bool); - void setTitle(const String&); - const String& overrideEncoding() const { return m_overrideEncoding; } - -#if PLATFORM(MAC) - void schedule(SchedulePair*); - void unschedule(SchedulePair*); -#endif - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - void addAllArchiveResources(Archive*); - void addArchiveResource(PassRefPtr<ArchiveResource>); - - // Return an ArchiveResource for the URL, either creating from live data or - // pulling from the ArchiveResourceCollection - PassRefPtr<ArchiveResource> subresource(const KURL&) const; - // Return the ArchiveResource for the URL only when loading an Archive - ArchiveResource* archiveResourceForURL(const KURL&) const; - - PassRefPtr<Archive> popArchiveForSubframe(const String& frameName); - void clearArchiveResources(); - void setParsedArchiveData(PassRefPtr<SharedBuffer>); - SharedBuffer* parsedArchiveData() const; - - PassRefPtr<ArchiveResource> mainResource() const; - void getSubresources(Vector<PassRefPtr<ArchiveResource> >&) const; - - bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&, const KURL&); -#endif -#ifndef NDEBUG - bool isSubstituteLoadPending(ResourceLoader*) const; -#endif - void cancelPendingSubstituteLoad(ResourceLoader*); - - void addResponse(const ResourceResponse&); - const ResponseVector& responses() const { return m_responses; } - - const NavigationAction& triggeringAction() const { return m_triggeringAction; } - void setTriggeringAction(const NavigationAction& action) { m_triggeringAction = action; } - void setOverrideEncoding(const String& encoding) { m_overrideEncoding = encoding; } - void setLastCheckedRequest(const ResourceRequest& request) { m_lastCheckedRequest = request; } - const ResourceRequest& lastCheckedRequest() { return m_lastCheckedRequest; } - - void stopRecordingResponses(); - const String& title() const { return m_pageTitle; } - KURL urlForHistory() const; - - void loadFromCachedPage(PassRefPtr<CachedPage>); - void setLoadingFromCachedPage(bool loading) { m_loadingFromCachedPage = loading; } - bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } - - void setDefersLoading(bool); - - bool startLoadingMainResource(unsigned long identifier); - void cancelMainResourceLoad(const ResourceError&); - - void iconLoadDecisionAvailable(); - - bool isLoadingMainResource() const; - bool isLoadingSubresources() const; - bool isLoadingPlugIns() const; - bool isLoadingMultipartContent() const; - - void stopLoadingPlugIns(); - void stopLoadingSubresources(); - - void addSubresourceLoader(ResourceLoader*); - void removeSubresourceLoader(ResourceLoader*); - void addPlugInStreamLoader(ResourceLoader*); - void removePlugInStreamLoader(ResourceLoader*); - - void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*); - - void setDeferMainResourceDataLoad(bool defer) { m_deferMainResourceDataLoad = defer; } - bool deferMainResourceDataLoad() const { return m_deferMainResourceDataLoad; } - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - bool scheduleApplicationCacheLoad(ResourceLoader*, const ResourceRequest&, const KURL& originalURL); - bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&); - - void setCandidateApplicationCacheGroup(ApplicationCacheGroup* group); - ApplicationCacheGroup* candidateApplicationCacheGroup() const { return m_candidateApplicationCacheGroup; } - - void setApplicationCache(PassRefPtr<ApplicationCache> applicationCache); - ApplicationCache* applicationCache() const { return m_applicationCache.get(); } - ApplicationCache* topLevelApplicationCache() const; - - ApplicationCache* mainResourceApplicationCache() const; -#endif - - protected: - DocumentLoader(const ResourceRequest&, const SubstituteData&); - - bool m_deferMainResourceDataLoad; - - private: - void setupForReplace(); - void commitIfReady(); - void clearErrors(); - void setMainDocumentError(const ResourceError&); - void commitLoad(const char*, int); - bool doesProgressiveLoad(const String& MIMEType) const; - - void deliverSubstituteResourcesAfterDelay(); - void substituteResourceDeliveryTimerFired(Timer<DocumentLoader>*); - - Frame* m_frame; - - RefPtr<MainResourceLoader> m_mainResourceLoader; - ResourceLoaderSet m_subresourceLoaders; - ResourceLoaderSet m_multipartSubresourceLoaders; - ResourceLoaderSet m_plugInStreamLoaders; - - RefPtr<SharedBuffer> m_mainResourceData; - - // A reference to actual request used to create the data source. - // This should only be used by the resourceLoadDelegate's - // identifierForInitialRequest:fromDatasource: method. It is - // not guaranteed to remain unchanged, as requests are mutable. - ResourceRequest m_originalRequest; - - SubstituteData m_substituteData; - - // A copy of the original request used to create the data source. - // We have to copy the request because requests are mutable. - ResourceRequest m_originalRequestCopy; - - // The 'working' request. It may be mutated - // several times from the original request to include additional - // headers, cookie information, canonicalization and redirects. - ResourceRequest m_request; - - ResourceResponse m_response; - - ResourceError m_mainDocumentError; - - bool m_committed; - bool m_isStopping; - bool m_loading; - bool m_gotFirstByte; - bool m_primaryLoadComplete; - bool m_isClientRedirect; - bool m_loadingFromCachedPage; - - String m_pageTitle; - - String m_overrideEncoding; - - // The action that triggered loading - we keep this around for the - // benefit of the various policy handlers. - NavigationAction m_triggeringAction; - - // The last request that we checked click policy for - kept around - // so we can avoid asking again needlessly. - ResourceRequest m_lastCheckedRequest; - - // We retain all the received responses so we can play back the - // WebResourceLoadDelegate messages if the item is loaded from the - // page cache. - ResponseVector m_responses; - bool m_stopRecordingResponses; - - typedef HashMap<RefPtr<ResourceLoader>, RefPtr<SubstituteResource> > SubstituteResourceMap; - SubstituteResourceMap m_pendingSubstituteResources; - Timer<DocumentLoader> m_substituteResourceDeliveryTimer; - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - OwnPtr<ArchiveResourceCollection> m_archiveResourceCollection; - RefPtr<SharedBuffer> m_parsedArchiveData; -#endif - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - // The application cache that the document loader is associated with (if any). - RefPtr<ApplicationCache> m_applicationCache; - - // Before an application cache has finished loading, this will be the candidate application - // group that the document loader is associated with. - ApplicationCacheGroup* m_candidateApplicationCacheGroup; - - // Once the main resource has finished loading, this is the application cache it was loaded from (if any). - RefPtr<ApplicationCache> m_mainResourceApplicationCache; -#endif - }; - -} - -#endif // DocumentLoader_h diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h deleted file mode 100644 index 8cab747..0000000 --- a/WebCore/loader/EmptyClients.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) 2006 Eric Seidel (eric@webkit.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef EmptyClients_h -#define EmptyClients_h - -#include "ChromeClient.h" -#include "ContextMenuClient.h" -#include "DragClient.h" -#include "DocumentLoader.h" -#include "EditCommand.h" -#include "EditorClient.h" -#include "FocusDirection.h" -#include "FloatRect.h" -#include "FrameLoaderClient.h" -#include "InspectorClient.h" -#include "ResourceError.h" -#include "SharedBuffer.h" - -/* - This file holds empty Client stubs for use by WebCore. - Viewless element needs to create a dummy Page->Frame->FrameView tree for use in parsing or executing JavaScript. - This tree depends heavily on Clients (usually provided by WebKit classes). - - This file was first created for SVGImage as it had no way to access the current Page (nor should it, - since Images are not tied to a page). - See http://bugs.webkit.org/show_bug.cgi?id=5971 for the original discussion about this file. - - Ideally, whenever you change a Client class, you should add a stub here. - Brittle, yes. Unfortunate, yes. Hopefully temporary. -*/ - -namespace WebCore { - -class EmptyChromeClient : public ChromeClient { -public: - virtual ~EmptyChromeClient() { } - virtual void chromeDestroyed() { } - - virtual void setWindowRect(const FloatRect&) { } - virtual FloatRect windowRect() { return FloatRect(); } - - virtual FloatRect pageRect() { return FloatRect(); } - - virtual float scaleFactor() { return 1.f; } - - virtual void focus() { } - virtual void unfocus() { } - - virtual bool canTakeFocus(FocusDirection) { return false; } - virtual void takeFocus(FocusDirection) { } - - virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&) { return 0; } - virtual void show() { } - - virtual bool canRunModal() { return false; } - virtual void runModal() { } - - virtual void setToolbarsVisible(bool) { } - virtual bool toolbarsVisible() { return false; } - - virtual void setStatusbarVisible(bool) { } - virtual bool statusbarVisible() { return false; } - - virtual void setScrollbarsVisible(bool) { } - virtual bool scrollbarsVisible() { return false; } - - virtual void setMenubarVisible(bool) { } - virtual bool menubarVisible() { return false; } - - virtual void setResizable(bool) { } - - virtual void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) { } - - virtual bool canRunBeforeUnloadConfirmPanel() { return false; } - virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { return true; } - - virtual void closeWindowSoon() { } - - virtual void runJavaScriptAlert(Frame*, const String&) { } - virtual bool runJavaScriptConfirm(Frame*, const String&) { return false; } - virtual bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result) { return false; } - virtual bool shouldInterruptJavaScript() { return false; } - - virtual void setStatusbarText(const String&) { } - - virtual bool tabsToLinks() const { return false; } - - virtual IntRect windowResizerRect() const { return IntRect(); } - virtual void addToDirtyRegion(const IntRect&) { } - virtual void scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect) { } - virtual void updateBackingStore() { } - - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false) { } - virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) { } - virtual IntPoint screenToWindow(const IntPoint& p) const { return p; } - virtual IntRect windowToScreen(const IntRect& r) const { return r; } - virtual PlatformWidget platformWindow() const { return 0; } - - virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) { } - - virtual void setToolTip(const String&) { } - - virtual void print(Frame*) { } - - virtual void exceededDatabaseQuota(Frame*, const String&) { } - - virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) { } -}; - -class EmptyFrameLoaderClient : public FrameLoaderClient { -public: - virtual ~EmptyFrameLoaderClient() { } - virtual void frameLoaderDestroyed() { } - - virtual bool hasWebView() const { return true; } // mainly for assertions - - virtual void makeRepresentation(DocumentLoader*) { } - virtual void forceLayout() { } - virtual void forceLayoutForNonHTML() { } - - virtual void updateHistoryForCommit() { } - - virtual void updateHistoryForBackForwardNavigation() { } - virtual void updateHistoryForReload() { } - virtual void updateHistoryForStandardLoad() { } - virtual void updateHistoryForInternalLoad() { } - - virtual void updateHistoryAfterClientRedirect() { } - - virtual void setCopiesOnScroll() { } - - virtual void detachedFromParent2() { } - virtual void detachedFromParent3() { } - - virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) { } - - virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&) { } - virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse) { } - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) { } - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) { } - virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&) { } - virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived) { } - virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) { } - virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&) { } - virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) { return false; } - - virtual void dispatchDidHandleOnloadEvents() { } - virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() { } - virtual void dispatchDidCancelClientRedirect() { } - virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate) { } - virtual void dispatchDidChangeLocationWithinPage() { } - virtual void dispatchWillClose() { } - virtual void dispatchDidReceiveIcon() { } - virtual void dispatchDidStartProvisionalLoad() { } - virtual void dispatchDidReceiveTitle(const String& title) { } - virtual void dispatchDidCommitLoad() { } - virtual void dispatchDidFailProvisionalLoad(const ResourceError&) { } - virtual void dispatchDidFailLoad(const ResourceError&) { } - virtual void dispatchDidFinishDocumentLoad() { } - virtual void dispatchDidFinishLoad() { } - virtual void dispatchDidFirstLayout() { } - - virtual Frame* dispatchCreatePage() { return 0; } - virtual void dispatchShow() { } - - virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&) { } - virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName) { } - virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>) { } - virtual void cancelPolicyCheck() { } - - virtual void dispatchUnableToImplementPolicy(const ResourceError&) { } - - virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) { } - - virtual void dispatchDidLoadMainResource(DocumentLoader*) { } - virtual void revertToProvisionalState(DocumentLoader*) { } - virtual void setMainDocumentError(DocumentLoader*, const ResourceError&) { } - - virtual void willChangeEstimatedProgress() { } - virtual void didChangeEstimatedProgress() { } - virtual void postProgressStartedNotification() { } - virtual void postProgressEstimateChangedNotification() { } - virtual void postProgressFinishedNotification() { } - - virtual void setMainFrameDocumentReady(bool) { } - - virtual void startDownload(const ResourceRequest&) { } - - virtual void willChangeTitle(DocumentLoader*) { } - virtual void didChangeTitle(DocumentLoader*) { } - - virtual void committedLoad(DocumentLoader*, const char*, int) { } - virtual void finishedLoading(DocumentLoader*) { } - - virtual ResourceError cancelledError(const ResourceRequest&) { return ResourceError(); } - virtual ResourceError blockedError(const ResourceRequest&) { return ResourceError(); } - virtual ResourceError cannotShowURLError(const ResourceRequest&) { return ResourceError(); } - virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) { return ResourceError(); } - - virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) { return ResourceError(); } - virtual ResourceError fileDoesNotExistError(const ResourceResponse&) { return ResourceError(); } - virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) { return ResourceError(); } - - virtual bool shouldFallBack(const ResourceError&) { return false; } - - virtual bool canHandleRequest(const ResourceRequest&) const { return false; } - virtual bool canShowMIMEType(const String& MIMEType) const { return false; } - virtual bool representationExistsForURLScheme(const String& URLScheme) const { return false; } - virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const { return ""; } - - virtual void frameLoadCompleted() { } - virtual void restoreViewState() { } - virtual void provisionalLoadStarted() { } - virtual bool shouldTreatURLAsSameAsCurrent(const KURL&) const { return false; } - virtual void addHistoryItemForFragmentScroll() { } - virtual void didFinishLoad() { } - virtual void prepareForDataSourceReplacement() { } - - virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) { return DocumentLoader::create(request, substituteData); } - virtual void setTitle(const String& title, const KURL&) { } - - virtual String userAgent(const KURL&) { return ""; } - - virtual void savePlatformDataToCachedPage(CachedPage*) { } - virtual void transitionToCommittedFromCachedPage(CachedPage*) { } - virtual void transitionToCommittedForNewPage() { } - - virtual void updateGlobalHistory(const KURL&) { } - virtual bool shouldGoToHistoryItem(HistoryItem*) const { return false; } - virtual void saveViewStateToItem(HistoryItem*) { } - virtual bool canCachePage() const { return false; } - - virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, - const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) { return 0; } - virtual Widget* createPlugin(const IntSize&,Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; } - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; } - - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) { return ObjectContentType(); } - virtual String overrideMediaType() const { return String(); } - - virtual void redirectDataToPlugin(Widget*) {} - virtual void windowObjectCleared() {} - virtual void didPerformFirstNavigation() const {} - - virtual void registerForIconNotification(bool listen) {} - -#if PLATFORM(MAC) - virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response) const { return response; } -#endif - -}; - -class EmptyEditorClient : public EditorClient { -public: - virtual ~EmptyEditorClient() { } - virtual void pageDestroyed() { } - - virtual bool shouldDeleteRange(Range*) { return false; } - virtual bool shouldShowDeleteInterface(HTMLElement*) { return false; } - virtual bool smartInsertDeleteEnabled() { return false; } - virtual bool isContinuousSpellCheckingEnabled() { return false; } - virtual void toggleContinuousSpellChecking() { } - virtual bool isGrammarCheckingEnabled() { return false; } - virtual void toggleGrammarChecking() { } - virtual int spellCheckerDocumentTag() { return -1; } - - virtual bool selectWordBeforeMenuEvent() { return false; } - virtual bool isEditable() { return false; } - - virtual bool shouldBeginEditing(Range*) { return false; } - virtual bool shouldEndEditing(Range*) { return false; } - virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction) { return false; } - // virtual bool shouldInsertNode(Node*, Range* replacingRange, WebViewInsertAction) { return false; } - virtual bool shouldInsertText(const String&, Range*, EditorInsertAction) { return false; } - virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting) { return false; } - - virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*) { return false; } - virtual bool shouldMoveRangeAfterDelete(Range*, Range*) { return false; } - // virtual bool shouldChangeTypingStyle(CSSStyleDeclaration* fromStyle, CSSStyleDeclaration* toStyle) { return false; } - // virtual bool doCommandBySelector(SEL selector) { return false; } - // - virtual void didBeginEditing() { } - virtual void respondToChangedContents() { } - virtual void respondToChangedSelection() { } - virtual void didEndEditing() { } - virtual void didWriteSelectionToPasteboard() { } - virtual void didSetSelectionTypesForPasteboard() { } - // virtual void webViewDidChangeTypingStyle:(NSNotification *)notification { } - // virtual void webViewDidChangeSelection:(NSNotification *)notification { } - // virtual NSUndoManager* undoManagerForWebView:(WebView *)webView { return 0; } - - virtual void registerCommandForUndo(PassRefPtr<EditCommand>) { } - virtual void registerCommandForRedo(PassRefPtr<EditCommand>) { } - virtual void clearUndoRedoOperations() { } - - virtual bool canUndo() const { return false; } - virtual bool canRedo() const { return false; } - - virtual void undo() { } - virtual void redo() { } - - virtual void handleKeyboardEvent(KeyboardEvent*) { } - virtual void handleInputMethodKeydown(KeyboardEvent*) { } - - virtual void textFieldDidBeginEditing(Element*) { } - virtual void textFieldDidEndEditing(Element*) { } - virtual void textDidChangeInTextField(Element*) { } - virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; } - virtual void textWillBeDeletedInTextField(Element*) { } - virtual void textDidChangeInTextArea(Element*) { } - -#if PLATFORM(MAC) - virtual void markedTextAbandoned(Frame*) { } - - virtual NSString* userVisibleString(NSURL*) { return 0; } -#ifdef BUILDING_ON_TIGER - virtual NSArray* pasteboardTypesForSelection(Frame*) { return 0; } -#endif -#endif - virtual void ignoreWordInSpellDocument(const String&) { } - virtual void learnWord(const String&) { } - virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) { } - virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) { } - virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { } - virtual void updateSpellingUIWithMisspelledWord(const String&) { } - virtual void showSpellingUI(bool show) { } - virtual bool spellingUIIsShowing() { return false; } - virtual void getGuessesForWord(const String&, Vector<String>& guesses) { } - virtual void setInputMethodState(bool enabled) { } - - -}; - -class EmptyContextMenuClient : public ContextMenuClient { -public: - virtual ~EmptyContextMenuClient() { } - virtual void contextMenuDestroyed() { } - - virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) { return 0; } - virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { } - - virtual void downloadURL(const KURL& url) { } - virtual void copyImageToClipboard(const HitTestResult&) { } - virtual void searchWithGoogle(const Frame*) { } - virtual void lookUpInDictionary(Frame*) { } - virtual void speak(const String&) { } - virtual void stopSpeaking() { } - -#if PLATFORM(MAC) - virtual void searchWithSpotlight() { } -#endif -}; - -class EmptyDragClient : public DragClient { -public: - virtual ~EmptyDragClient() {} - virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*) { } - virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*) { } - virtual DragDestinationAction actionMaskForDrag(DragData*) { return DragDestinationActionNone; } - virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint&) { return DragSourceActionNone; } - virtual void startDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool) { } - virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*) { return 0; } - virtual void dragControllerDestroyed() { } -}; - -class EmptyInspectorClient : public InspectorClient { -public: - virtual ~EmptyInspectorClient() { } - - virtual void inspectorDestroyed() { } - - virtual Page* createPage() { return 0; }; - - virtual String localizedStringsURL() { return String(); } - - virtual void showWindow() { } - virtual void closeWindow() { } - - virtual void attachWindow() { } - virtual void detachWindow() { } - - virtual void setAttachedWindowHeight(unsigned) { } - - virtual void highlight(Node*) { } - virtual void hideHighlight() { } - virtual void inspectedURLChanged(const String& newURL) { } - - virtual void populateSetting(const String& key, InspectorController::Setting&) { } - virtual void storeSetting(const String& key, const InspectorController::Setting&) { } - virtual void removeSetting(const String& key) { } -}; - -} - -#endif // EmptyClients_h diff --git a/WebCore/loader/FTPDirectoryDocument.cpp b/WebCore/loader/FTPDirectoryDocument.cpp deleted file mode 100644 index 0a7e91e..0000000 --- a/WebCore/loader/FTPDirectoryDocument.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#if ENABLE(FTPDIR) -#include "FTPDirectoryDocument.h" - -#include "CharacterNames.h" -#include "CString.h" -#include "HTMLNames.h" -#include "HTMLTableElement.h" -#include "HTMLTokenizer.h" -#include "LocalizedStrings.h" -#include "Logging.h" -#include "FTPDirectoryParser.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "SharedBuffer.h" -#include "Text.h" - -#if PLATFORM(QT) -#include <QDateTime> -// On Windows, use the threadsafe *_r functions provided by pthread. -#elif PLATFORM(WIN_OS) && (USE(PTHREADS) || HAVE(PTHREAD_H)) -#include <pthread.h> -#endif - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -class FTPDirectoryTokenizer : public HTMLTokenizer { -public: - FTPDirectoryTokenizer(HTMLDocument*); - - virtual bool write(const SegmentedString&, bool appendData); - virtual void finish(); - - virtual bool isWaitingForScripts() const { return false; } - - inline void checkBuffer(int len = 10) - { - if ((m_dest - m_buffer) > m_size - len) { - // Enlarge buffer - int newSize = max(m_size * 2, m_size + len); - int oldOffset = m_dest - m_buffer; - m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar))); - m_dest = m_buffer + oldOffset; - m_size = newSize; - } - } - -private: - // The tokenizer will attempt to load the document template specified via the preference - // Failing that, it will fall back and create the basic document which will have a minimal - // table for presenting the FTP directory in a useful manner - bool loadDocumentTemplate(); - void createBasicDocument(); - - void parseAndAppendOneLine(const String&); - void appendEntry(const String& name, const String& size, const String& date, bool isDirectory); - PassRefPtr<Element> createTDForFilename(const String&); - - Document* m_doc; - RefPtr<HTMLTableElement> m_tableElement; - - bool m_skipLF; - bool m_parsedTemplate; - - int m_size; - UChar* m_buffer; - UChar* m_dest; - String m_carryOver; - - ListState m_listState; -}; - -FTPDirectoryTokenizer::FTPDirectoryTokenizer(HTMLDocument* doc) - : HTMLTokenizer(doc, false) - , m_doc(doc) - , m_skipLF(false) - , m_parsedTemplate(false) - , m_size(254) - , m_buffer(static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size))) - , m_dest(m_buffer) -{ -} - -void FTPDirectoryTokenizer::appendEntry(const String& filename, const String& size, const String& date, bool isDirectory) -{ - ExceptionCode ec; - - RefPtr<Element> rowElement = m_tableElement->insertRow(-1, ec); - rowElement->setAttribute("class", "ftpDirectoryEntryRow", ec); - - RefPtr<Element> element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec); - element->appendChild(new Text(m_doc, String(&noBreakSpace, 1)), ec); - if (isDirectory) - element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeDirectory", ec); - else - element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeFile", ec); - rowElement->appendChild(element, ec); - - element = createTDForFilename(filename); - element->setAttribute("class", "ftpDirectoryFileName", ec); - rowElement->appendChild(element, ec); - - element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec); - element->appendChild(new Text(m_doc, date), ec); - element->setAttribute("class", "ftpDirectoryFileDate", ec); - rowElement->appendChild(element, ec); - - element = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec); - element->appendChild(new Text(m_doc, size), ec); - element->setAttribute("class", "ftpDirectoryFileSize", ec); - rowElement->appendChild(element, ec); -} - -PassRefPtr<Element> FTPDirectoryTokenizer::createTDForFilename(const String& filename) -{ - ExceptionCode ec; - - String fullURL = m_doc->baseURL().string(); - if (fullURL[fullURL.length() - 1] == '/') - fullURL.append(filename); - else - fullURL.append("/" + filename); - - RefPtr<Element> anchorElement = m_doc->createElementNS(xhtmlNamespaceURI, "a", ec); - anchorElement->setAttribute("href", fullURL, ec); - anchorElement->appendChild(new Text(m_doc, filename), ec); - - RefPtr<Element> tdElement = m_doc->createElementNS(xhtmlNamespaceURI, "td", ec); - tdElement->appendChild(anchorElement, ec); - - return tdElement.release(); -} - -static String processFilesizeString(const String& size, bool isDirectory) -{ - if (isDirectory) - return "--"; - - bool valid; - int64_t bytes = size.toUInt64(&valid); - if (!valid) - return unknownFileSizeText(); - - if (bytes < 1000000) - return String::format("%.2f KB", static_cast<float>(bytes)/1000); - - if (bytes < 1000000000) - return String::format("%.2f MB", static_cast<float>(bytes)/1000000); - - return String::format("%.2f GB", static_cast<float>(bytes)/1000000000); -} - -static bool wasLastDayOfMonth(int year, int month, int day) -{ - static int lastDays[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - if (month < 0 || month > 11) - return false; - - if (month == 2) { - if (year % 4 == 0 && (year % 100 || year % 400 == 0)) { - if (day == 29) - return true; - return false; - } - - if (day == 28) - return true; - return false; - } - - return lastDays[month] == day; -} - -#if PLATFORM(QT) - -/*! - Replacement for localtime_r() which is not available on MinGW. - - We use this on all of Qt's platforms for portability. - */ -struct tm gmtimeQt(const QDateTime &input) -{ - tm result; - - const QDate date(input.date()); - result.tm_year = date.year() - 1900; - result.tm_mon = date.month(); - result.tm_mday = date.day(); - result.tm_wday = date.dayOfWeek(); - result.tm_yday = date.dayOfYear(); - - const QTime time(input.time()); - result.tm_sec = time.second(); - result.tm_min = time.minute(); - result.tm_hour = time.hour(); - - return result; -} - -static struct tm *localTimeQt(const time_t *const timep, struct tm *result) -{ - const QDateTime dt(QDateTime::fromTime_t(*timep)); - *result = WebCore::gmtimeQt(dt.toLocalTime()); - return result; -} - -#define localtime_r(x, y) localTimeQt(x, y) -#elif PLATFORM(WIN_OS) && !defined(localtime_r) -#define localtime_r(x, y) localtime_s((y), (x)) -#endif - -static String processFileDateString(const FTPTime& fileTime) -{ - // FIXME: Need to localize this string? - - String timeOfDay; - - if (!(fileTime.tm_hour == 0 && fileTime.tm_min == 0 && fileTime.tm_sec == 0)) { - int hour = fileTime.tm_hour; - ASSERT(hour >= 0 && hour < 24); - - if (hour < 12) { - if (hour == 0) - hour = 12; - timeOfDay = String::format(", %i:%02i AM", hour, fileTime.tm_min); - } else { - hour = hour - 12; - if (hour == 0) - hour = 12; - timeOfDay = String::format(", %i:%02i PM", hour, fileTime.tm_min); - } - } - - // If it was today or yesterday, lets just do that - but we have to compare to the current time - struct tm now; - time_t now_t = time(NULL); - localtime_r(&now_t, &now); - - // localtime does "year = current year - 1900", compensate for that for readability and comparison purposes - now.tm_year += 1900; - - if (fileTime.tm_year == now.tm_year) { - if (fileTime.tm_mon == now.tm_mon) { - if (fileTime.tm_mday == now.tm_mday) - return "Today" + timeOfDay; - if (fileTime.tm_mday == now.tm_mday - 1) - return "Yesterday" + timeOfDay; - } - - if (now.tm_mday == 1 && (now.tm_mon == fileTime.tm_mon + 1 || now.tm_mon == 0 && fileTime.tm_mon == 11) && - wasLastDayOfMonth(fileTime.tm_year, fileTime.tm_mon, fileTime.tm_mday)) - return "Yesterday" + timeOfDay; - } - - if (fileTime.tm_year == now.tm_year - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.tm_mon == 1 && now.tm_mday == 1) - return "Yesterday" + timeOfDay; - - static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; - - int month = fileTime.tm_mon; - if (month < 0 || month > 11) - month = 12; - - String dateString; - - if (fileTime.tm_year > -1) - dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, fileTime.tm_year); - else - dateString = String::format("%s %i, %i", months[month], fileTime.tm_mday, now.tm_year); - - return dateString + timeOfDay; -} - -void FTPDirectoryTokenizer::parseAndAppendOneLine(const String& inputLine) -{ - ListResult result; - - FTPEntryType typeResult = parseOneFTPLine(inputLine.latin1().data(), m_listState, result); - - // FTPMiscEntry is a comment or usage statistic which we don't care about, and junk is invalid data - bail in these 2 cases - if (typeResult == FTPMiscEntry || typeResult == FTPJunkEntry) - return; - - String filename(result.filename, result.filenameLength); - if (result.type == FTPDirectoryEntry) { - filename.append("/"); - - // We have no interest in linking to "current directory" - if (filename == "./") - return; - } - - LOG(FTP, "Appending entry - %s, %s", filename.ascii().data(), result.fileSize.ascii().data()); - - appendEntry(filename, processFilesizeString(result.fileSize, result.type == FTPDirectoryEntry), processFileDateString(result.modifiedTime), result.type == FTPDirectoryEntry); -} - -bool FTPDirectoryTokenizer::loadDocumentTemplate() -{ - static RefPtr<SharedBuffer> templateDocumentData; - // FIXME: Instead of storing the data, we'd rather actually parse the template data into the template Document once, - // store that document, then "copy" it whenever we get an FTP directory listing. There are complexities with this - // approach that make it worth putting this off. - - if (!templateDocumentData) { - Settings* settings = m_doc->settings(); - if (settings) - templateDocumentData = SharedBuffer::createWithContentsOfFile(settings->ftpDirectoryTemplatePath()); - if (templateDocumentData) - LOG(FTP, "Loaded FTPDirectoryTemplate of length %i\n", templateDocumentData->size()); - } - - if (!templateDocumentData) { - LOG_ERROR("Could not load templateData"); - return false; - } - - // Tokenize the template as an HTML document synchronously - setForceSynchronous(true); - HTMLTokenizer::write(String(templateDocumentData->data(), templateDocumentData->size()), true); - setForceSynchronous(false); - - RefPtr<Element> tableElement = m_doc->getElementById("ftpDirectoryTable"); - if (!tableElement) - LOG_ERROR("Unable to find element by id \"ftpDirectoryTable\" in the template document."); - else if (!tableElement->hasTagName(tableTag)) - LOG_ERROR("Element of id \"ftpDirectoryTable\" is not a table element"); - else - m_tableElement = static_cast<HTMLTableElement*>(tableElement.get()); - - // Bail if we found the table element - if (m_tableElement) - return true; - - // Otherwise create one manually - ExceptionCode ec; - tableElement = m_doc->createElementNS(xhtmlNamespaceURI, "table", ec); - m_tableElement = static_cast<HTMLTableElement*>(tableElement.get()); - m_tableElement->setAttribute("id", "ftpDirectoryTable", ec); - - // If we didn't find the table element, lets try to append our own to the body - // If that fails for some reason, cram it on the end of the document as a last - // ditch effort - if (Element* body = m_doc->body()) - body->appendChild(m_tableElement, ec); - else - m_doc->appendChild(m_tableElement, ec); - - return true; -} - -void FTPDirectoryTokenizer::createBasicDocument() -{ - LOG(FTP, "Creating a basic FTP document structure as no template was loaded"); - - // FIXME: Make this "basic document" more acceptable - - ExceptionCode ec; - - RefPtr<Element> bodyElement = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec); - - m_doc->appendChild(bodyElement, ec); - - RefPtr<Element> tableElement = m_doc->createElementNS(xhtmlNamespaceURI, "table", ec); - m_tableElement = static_cast<HTMLTableElement*>(tableElement.get()); - m_tableElement->setAttribute("id", "ftpDirectoryTable", ec); - - bodyElement->appendChild(m_tableElement, ec); -} - -bool FTPDirectoryTokenizer::write(const SegmentedString& s, bool appendData) -{ - // Make sure we have the table element to append to by loading the template set in the pref, or - // creating a very basic document with the appropriate table - if (!m_tableElement) { - if (!loadDocumentTemplate()) - createBasicDocument(); - ASSERT(m_tableElement); - } - - bool foundNewLine = false; - - m_dest = m_buffer; - SegmentedString str = s; - while (!str.isEmpty()) { - UChar c = *str; - - if (c == '\r') { - *m_dest++ = '\n'; - foundNewLine = true; - // possibly skip an LF in the case of an CRLF sequence - m_skipLF = true; - } else if (c == '\n') { - if (!m_skipLF) - *m_dest++ = c; - else - m_skipLF = false; - } else { - *m_dest++ = c; - m_skipLF = false; - } - - str.advance(); - - // Maybe enlarge the buffer - checkBuffer(); - } - - if (!foundNewLine) { - m_dest = m_buffer; - return false; - } - - UChar* start = m_buffer; - UChar* cursor = start; - - while (cursor < m_dest) { - if (*cursor == '\n') { - m_carryOver.append(String(start, cursor - start)); - LOG(FTP, "%s", m_carryOver.ascii().data()); - parseAndAppendOneLine(m_carryOver); - m_carryOver = String(); - - start = ++cursor; - } else - cursor++; - } - - // Copy the partial line we have left to the carryover buffer - if (cursor - start > 1) - m_carryOver.append(String(start, cursor - start - 1)); - - return false; -} - -void FTPDirectoryTokenizer::finish() -{ - // Possible the last line in the listing had no newline, so try to parse it now - if (!m_carryOver.isEmpty()) { - parseAndAppendOneLine(m_carryOver); - m_carryOver = String(); - } - - m_tableElement = 0; - fastFree(m_buffer); - - HTMLTokenizer::finish(); -} - -FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame) - : HTMLDocument(frame) -{ -#ifndef NDEBUG - LogFTP.state = WTFLogChannelOn; -#endif -} - -Tokenizer* FTPDirectoryDocument::createTokenizer() -{ - return new FTPDirectoryTokenizer(this); -} - -} - -#endif // ENABLE(FTPDIR) diff --git a/WebCore/loader/FTPDirectoryDocument.h b/WebCore/loader/FTPDirectoryDocument.h deleted file mode 100644 index ecc6f73..0000000 --- a/WebCore/loader/FTPDirectoryDocument.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FTPDirectoryDocument_h -#define FTPDirectoryDocument_h - -#include "HTMLDocument.h" - -namespace WebCore { - -class DOMImplementation; - -class FTPDirectoryDocument : public HTMLDocument { -public: - static PassRefPtr<FTPDirectoryDocument> create(Frame* frame) - { - return new FTPDirectoryDocument(frame); - } - -private: - FTPDirectoryDocument(Frame*); - virtual Tokenizer* createTokenizer(); -}; - -} // namespace WebCore - -#endif // FTPDirectoryDocument_h diff --git a/WebCore/loader/FTPDirectoryParser.cpp b/WebCore/loader/FTPDirectoryParser.cpp deleted file mode 100644 index 8c76e97..0000000 --- a/WebCore/loader/FTPDirectoryParser.cpp +++ /dev/null @@ -1,1624 +0,0 @@ -/* - * Copyright (C) 2002 Cyrus Patel <cyp@fb14.uni-mainz.de> - * (C) 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 Lesser General Public - * License 2.1 as published by the Free Software Foundation. - * - * 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 was originally Mozilla code, titled ParseFTPList.cpp -// Original version of this file can currently be found at: http://mxr.mozilla.org/mozilla1.8/source/netwerk/streamconv/converters/ParseFTPList.cpp - -#include "config.h" -#if ENABLE(FTPDIR) -#include "FTPDirectoryParser.h" - -#if PLATFORM(QT) -#include <QDateTime> -// On Windows, use the threadsafe *_r functions provided by pthread. -#elif PLATFORM(WIN_OS) && (USE(PTHREADS) || HAVE(PTHREAD_H)) -#include <pthread.h> -#endif - -#include <wtf/ASCIICType.h> -#include <stdio.h> - -using namespace WTF; - -namespace WebCore { -#if PLATFORM(QT) && defined(Q_WS_WIN32) -// Defined in FTPDirectoryDocument.cpp. -struct tm gmtimeQt(const QDateTime &input); - -static struct tm *gmtimeQt(const time_t *const timep, struct tm *result) -{ - const QDateTime dt(QDateTime::fromTime_t(*timep)); - *result = WebCore::gmtimeQt(dt); - return result; -} - -#define gmtime_r(x, y) gmtimeQt(x, y) -#elif PLATFORM(WIN_OS) && !defined(gmtime_r) -#define gmtime_r(x, y) gmtime_s((y), (x)) -#endif - -FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& result) -{ - result.clear(); - - if (!line) - return FTPJunkEntry; - - state.numLines++; - - /* carry buffer is only valid from one line to the next */ - unsigned int carry_buf_len = state.carryBufferLength; - state.carryBufferLength = 0; - - unsigned linelen = 0; - - /* strip leading whitespace */ - while (*line == ' ' || *line == '\t') - line++; - - /* line is terminated at first '\0' or '\n' */ - const char* p = line; - while (*p && *p != '\n') - p++; - linelen = p - line; - - if (linelen > 0 && *p == '\n' && *(p-1) == '\r') - linelen--; - - /* DON'T strip trailing whitespace. */ - - if (linelen > 0) - { - static const char *month_names = "JanFebMarAprMayJunJulAugSepOctNovDec"; - const char *tokens[16]; /* 16 is more than enough */ - unsigned int toklen[(sizeof(tokens)/sizeof(tokens[0]))]; - unsigned int linelen_sans_wsp; // line length sans whitespace - unsigned int numtoks = 0; - unsigned int tokmarker = 0; /* extra info for lstyle handler */ - unsigned int month_num = 0; - char tbuf[4]; - int lstyle = 0; - - if (carry_buf_len) /* VMS long filename carryover buffer */ - { - tokens[0] = state.carryBuffer; - toklen[0] = carry_buf_len; - numtoks++; - } - - unsigned int pos = 0; - while (pos < linelen && numtoks < (sizeof(tokens)/sizeof(tokens[0])) ) - { - while (pos < linelen && - (line[pos] == ' ' || line[pos] == '\t' || line[pos] == '\r')) - pos++; - if (pos < linelen) - { - tokens[numtoks] = &line[pos]; - while (pos < linelen && - (line[pos] != ' ' && line[pos] != '\t' && line[pos] != '\r')) - pos++; - if (tokens[numtoks] != &line[pos]) - { - toklen[numtoks] = (&line[pos] - tokens[numtoks]); - numtoks++; - } - } - } - - linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0]; - if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) ) - { - pos = linelen; - while (pos > 0 && (line[pos-1] == ' ' || line[pos-1] == '\t')) - pos--; - linelen_sans_wsp = pos; - } - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -#if defined(SUPPORT_EPLF) - /* EPLF handling must come somewhere before /bin/dls handling. */ - if (!lstyle && (!state.listStyle || state.listStyle == 'E')) - { - if (*line == '+' && linelen > 4 && numtoks >= 2) - { - pos = 1; - while (pos < (linelen-1)) - { - p = &line[pos++]; - if (*p == '/') - result.type = FTPDirectoryEntry; /* its a dir */ - else if (*p == 'r') - result.type = FTPFileEntry; /* its a file */ - else if (*p == 'm') - { - if (isASCIIDigit(line[pos])) - { - while (pos < linelen && isASCIIDigit(line[pos])) - pos++; - if (pos < linelen && line[pos] == ',') - { - unsigned long long seconds = 0; - sscanf(p + 1, "%llu", &seconds); - time_t t = static_cast<time_t>(seconds); - - // FIXME: This code has the year 2038 bug - gmtime_r(&t, &result.modifiedTime); - result.modifiedTime.tm_year += 1900; - } - } - } - else if (*p == 's') - { - if (isASCIIDigit(line[pos])) - { - while (pos < linelen && isASCIIDigit(line[pos])) - pos++; - if (pos < linelen && line[pos] == ',') - result.fileSize = String(p + 1, &line[pos] - p + 1); - } - } - else if (isASCIIAlpha(*p)) /* 'i'/'up' or unknown "fact" (property) */ - { - while (pos < linelen && *++p != ',') - pos++; - } - else if (*p != '\t' || (p+1) != tokens[1]) - { - break; /* its not EPLF after all */ - } - else - { - state.parsedOne = true; - state.listStyle = lstyle = 'E'; - - p = &(line[linelen_sans_wsp]); - result.filename = tokens[1]; - result.filenameLength = p - tokens[1]; - - if (!result.type) /* access denied */ - { - result.type = FTPFileEntry; /* is assuming 'f'ile correct? */ - return FTPJunkEntry; /* NO! junk it. */ - } - return result.type; - } - if (pos >= (linelen-1) || line[pos] != ',') - break; - pos++; - } /* while (pos < linelen) */ - result.clear(); - } /* if (*line == '+' && linelen > 4 && numtoks >= 2) */ - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'E')) */ -#endif /* SUPPORT_EPLF */ - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_VMS) - if (!lstyle && (!state.listStyle || state.listStyle == 'V')) - { /* try VMS Multinet/UCX/CMS server */ - /* - * Legal characters in a VMS file/dir spec are [A-Z0-9$.-_~]. - * '$' cannot begin a filename and `-' cannot be used as the first - * or last character. '.' is only valid as a directory separator - * and <file>.<type> separator. A canonical filename spec might look - * like this: DISK$VOL:[DIR1.DIR2.DIR3]FILE.TYPE;123 - * All VMS FTP servers LIST in uppercase. - * - * We need to be picky about this in order to support - * multi-line listings correctly. - */ - if (!state.parsedOne && - (numtoks == 1 || (numtoks == 2 && toklen[0] == 9 && - memcmp(tokens[0], "Directory", 9)==0 ))) - { - /* If no dirstyle has been detected yet, and this line is a - * VMS list's dirname, then turn on VMS dirstyle. - * eg "ACA:[ANONYMOUS]", "DISK$FTP:[ANONYMOUS]", "SYS$ANONFTP:" - */ - p = tokens[0]; - pos = toklen[0]; - if (numtoks == 2) - { - p = tokens[1]; - pos = toklen[1]; - } - pos--; - if (pos >= 3) - { - while (pos > 0 && p[pos] != '[') - { - pos--; - if (p[pos] == '-' || p[pos] == '$') - { - if (pos == 0 || p[pos-1] == '[' || p[pos-1] == '.' || - (p[pos] == '-' && (p[pos+1] == ']' || p[pos+1] == '.'))) - break; - } - else if (p[pos] != '.' && p[pos] != '~' && - !isASCIIDigit(p[pos]) && !isASCIIAlpha(p[pos])) - break; - else if (isASCIIAlpha(p[pos]) && p[pos] != toASCIIUpper(p[pos])) - break; - } - if (pos > 0) - { - pos--; - if (p[pos] != ':' || p[pos+1] != '[') - pos = 0; - } - } - if (pos > 0 && p[pos] == ':') - { - while (pos > 0) - { - pos--; - if (p[pos] != '$' && p[pos] != '_' && p[pos] != '-' && - p[pos] != '~' && !isASCIIDigit(p[pos]) && !isASCIIAlpha(p[pos])) - break; - else if (isASCIIAlpha(p[pos]) && p[pos] != toASCIIUpper(p[pos])) - break; - } - if (pos == 0) - { - state.listStyle = 'V'; - return FTPJunkEntry; /* its junk */ - } - } - /* fallthrough */ - } - else if ((tokens[0][toklen[0]-1]) != ';') - { - if (numtoks == 1 && (state.listStyle == 'V' && !carry_buf_len)) - lstyle = 'V'; - else if (numtoks < 4) - ; - else if (toklen[1] >= 10 && memcmp(tokens[1], "%RMS-E-PRV", 10) == 0) - lstyle = 'V'; - else if ((&line[linelen] - tokens[1]) >= 22 && - memcmp(tokens[1], "insufficient privilege", 22) == 0) - lstyle = 'V'; - else if (numtoks != 4 && numtoks != 6) - ; - else if (numtoks == 6 && ( - toklen[5] < 4 || *tokens[5] != '(' || /* perms */ - (tokens[5][toklen[5]-1]) != ')' )) - ; - else if ( (toklen[2] == 10 || toklen[2] == 11) && - (tokens[2][toklen[2]-5]) == '-' && - (tokens[2][toklen[2]-9]) == '-' && - (((toklen[3]==4 || toklen[3]==5 || toklen[3]==7 || toklen[3]==8) && - (tokens[3][toklen[3]-3]) == ':' ) || - ((toklen[3]==10 || toklen[3]==11 ) && - (tokens[3][toklen[3]-3]) == '.' ) - ) && /* time in [H]H:MM[:SS[.CC]] format */ - isASCIIDigit(*tokens[1]) && /* size */ - isASCIIDigit(*tokens[2]) && /* date */ - isASCIIDigit(*tokens[3]) /* time */ - ) - { - lstyle = 'V'; - } - if (lstyle == 'V') - { - /* - * MultiNet FTP: - * LOGIN.COM;2 1 4-NOV-1994 04:09 [ANONYMOUS] (RWE,RWE,,) - * PUB.DIR;1 1 27-JAN-1994 14:46 [ANONYMOUS] (RWE,RWE,RE,RWE) - * README.FTP;1 %RMS-E-PRV, insufficient privilege or file protection violation - * ROUSSOS.DIR;1 1 27-JAN-1994 14:48 [CS,ROUSSOS] (RWE,RWE,RE,R) - * S67-50903.JPG;1 328 22-SEP-1998 16:19 [ANONYMOUS] (RWED,RWED,,) - * UCX FTP: - * CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,) - * CMU/VMS-IP FTP - * [VMSSERV.FILES]ALARM.DIR;1 1/3 5-MAR-1993 18:09 - * TCPware FTP - * FOO.BAR;1 4 5-MAR-1993 18:09:01.12 - * Long filename example: - * THIS-IS-A-LONG-VMS-FILENAME.AND-THIS-IS-A-LONG-VMS-FILETYPE\r\n - * 213[/nnn] 29-JAN-1996 03:33[:nn] [ANONYMOU,ANONYMOUS] (RWED,RWED,,) - */ - tokmarker = 0; - p = tokens[0]; - pos = 0; - if (*p == '[' && toklen[0] >= 4) /* CMU style */ - { - if (p[1] != ']') - { - p++; - pos++; - } - while (lstyle && pos < toklen[0] && *p != ']') - { - if (*p != '$' && *p != '.' && *p != '_' && *p != '-' && - *p != '~' && !isASCIIDigit(*p) && !isASCIIAlpha(*p)) - lstyle = 0; - pos++; - p++; - } - if (lstyle && pos < (toklen[0]-1) && *p == ']') - { - pos++; - p++; - tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */ - } - } - while (lstyle && pos < toklen[0] && *p != ';') - { - if (*p != '$' && *p != '.' && *p != '_' && *p != '-' && - *p != '~' && !isASCIIDigit(*p) && !isASCIIAlpha(*p)) - lstyle = 0; - else if (isASCIIAlpha(*p) && *p != toASCIIUpper(*p)) - lstyle = 0; - p++; - pos++; - } - if (lstyle && *p == ';') - { - if (pos == 0 || pos == (toklen[0]-1)) - lstyle = 0; - for (pos++;lstyle && pos < toklen[0];pos++) - { - if (!isASCIIDigit(tokens[0][pos])) - lstyle = 0; - } - } - pos = (p - tokens[0]); /* => fnlength sans ";####" */ - pos -= tokmarker; /* => fnlength sans "[DIR1.DIR2.etc]" */ - p = &(tokens[0][tokmarker]); /* offset of basename */ - - if (!lstyle || pos > 80) /* VMS filenames can't be longer than that */ - { - lstyle = 0; - } - else if (numtoks == 1) - { - /* if VMS has been detected and there is only one token and that - * token was a VMS filename then this is a multiline VMS LIST entry. - */ - if (pos >= (sizeof(state.carryBuffer)-1)) - pos = (sizeof(state.carryBuffer)-1); /* shouldn't happen */ - memcpy( state.carryBuffer, p, pos ); - state.carryBufferLength = pos; - return FTPJunkEntry; /* tell caller to treat as junk */ - } - else if (isASCIIDigit(*tokens[1])) /* not no-privs message */ - { - for (pos = 0; lstyle && pos < (toklen[1]); pos++) - { - if (!isASCIIDigit((tokens[1][pos])) && (tokens[1][pos]) != '/') - lstyle = 0; - } - if (lstyle && numtoks > 4) /* Multinet or UCX but not CMU */ - { - for (pos = 1; lstyle && pos < (toklen[5]-1); pos++) - { - p = &(tokens[5][pos]); - if (*p!='R' && *p!='W' && *p!='E' && *p!='D' && *p!=',') - lstyle = 0; - } - } - } - } /* passed initial tests */ - } /* else if ((tokens[0][toklen[0]-1]) != ';') */ - - if (lstyle == 'V') - { - state.parsedOne = true; - state.listStyle = lstyle; - - if (isASCIIDigit(*tokens[1])) /* not permission denied etc */ - { - /* strip leading directory name */ - if (*tokens[0] == '[') /* CMU server */ - { - pos = toklen[0]-1; - p = tokens[0]+1; - while (*p != ']') - { - p++; - pos--; - } - toklen[0] = --pos; - tokens[0] = ++p; - } - pos = 0; - while (pos < toklen[0] && (tokens[0][pos]) != ';') - pos++; - - result.caseSensitive = true; - result.type = FTPFileEntry; - result.filename = tokens[0]; - result.filenameLength = pos; - - if (pos > 4) - { - p = &(tokens[0][pos-4]); - if (p[0] == '.' && p[1] == 'D' && p[2] == 'I' && p[3] == 'R') - { - result.filenameLength -= 4; - result.type = FTPDirectoryEntry; - } - } - - if (result.type != FTPDirectoryEntry) - { - /* #### or used/allocated form. If used/allocated form, then - * 'used' is the size in bytes if and only if 'used'<=allocated. - * If 'used' is size in bytes then it can be > 2^32 - * If 'used' is not size in bytes then it is size in blocks. - */ - pos = 0; - while (pos < toklen[1] && (tokens[1][pos]) != '/') - pos++; - -/* - * I've never seen size come back in bytes, its always in blocks, and - * the following test fails. So, always perform the "size in blocks". - * I'm leaving the "size in bytes" code if'd out in case we ever need - * to re-instate it. -*/ -#if 0 - if (pos < toklen[1] && ( (pos<<1) > (toklen[1]-1) || - (strtoul(tokens[1], (char **)0, 10) > - strtoul(tokens[1]+pos+1, (char **)0, 10)) )) - { /* size is in bytes */ - if (pos > (sizeof(result.fe_size)-1)) - pos = sizeof(result.fe_size)-1; - memcpy( result.fe_size, tokens[1], pos ); - result.fe_size[pos] = '\0'; - } - else /* size is in blocks */ -#endif - { - /* size requires multiplication by blocksize. - * - * We could assume blocksize is 512 (like Lynx does) and - * shift by 9, but that might not be right. Even if it - * were, doing that wouldn't reflect what the file's - * real size was. The sanest thing to do is not use the - * LISTing's filesize, so we won't (like ftpmirror). - * - * ulltoa(((unsigned long long)fsz)<<9, result.fe_size, 10); - * - * A block is always 512 bytes on OpenVMS, compute size. - * So its rounded up to the next block, so what, its better - * than not showing the size at all. - * A block is always 512 bytes on OpenVMS, compute size. - * So its rounded up to the next block, so what, its better - * than not showing the size at all. - */ - uint64_t size = strtoul(tokens[1], NULL, 10) * 512; - result.fileSize = String::number(size); - } - - } /* if (result.type != FTPDirectoryEntry) */ - - p = tokens[2] + 2; - if (*p == '-') - p++; - tbuf[0] = p[0]; - tbuf[1] = toASCIILower(p[1]); - tbuf[2] = toASCIILower(p[2]); - month_num = 0; - for (pos = 0; pos < (12*3); pos+=3) - { - if (tbuf[0] == month_names[pos+0] && - tbuf[1] == month_names[pos+1] && - tbuf[2] == month_names[pos+2]) - break; - month_num++; - } - if (month_num >= 12) - month_num = 0; - result.modifiedTime.tm_mon = month_num; - result.modifiedTime.tm_mday = atoi(tokens[2]); - result.modifiedTime.tm_year = atoi(p+4); // NSPR wants year as XXXX - - p = tokens[3] + 2; - if (*p == ':') - p++; - if (p[2] == ':') - result.modifiedTime.tm_sec = atoi(p+3); - result.modifiedTime.tm_hour = atoi(tokens[3]); - result.modifiedTime.tm_min = atoi(p); - - return result.type; - - } /* if (isASCIIDigit(*tokens[1])) */ - - return FTPJunkEntry; /* junk */ - - } /* if (lstyle == 'V') */ - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'V')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_CMS) - /* Virtual Machine/Conversational Monitor System (IBM Mainframe) */ - if (!lstyle && (!state.listStyle || state.listStyle == 'C')) /* VM/CMS */ - { - /* LISTing according to mirror.pl - * Filename FileType Fm Format Lrecl Records Blocks Date Time - * LASTING GLOBALV A1 V 41 21 1 9/16/91 15:10:32 - * J43401 NETLOG A0 V 77 1 1 9/12/91 12:36:04 - * PROFILE EXEC A1 V 17 3 1 9/12/91 12:39:07 - * DIRUNIX SCRIPT A1 V 77 1216 17 1/04/93 20:30:47 - * MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27 - * BADY2K TEXT A0 V 1 1 1 1/03/102 10:11:12 - * AUTHORS A1 DIR - - - 9/20/99 10:31:11 - * - * LISTing from vm.marist.edu and vm.sc.edu - * 220-FTPSERVE IBM VM Level 420 at VM.MARIST.EDU, 04:58:12 EDT WEDNESDAY 2002-07-10 - * AUTHORS DIR - - - 1999-09-20 10:31:11 - - * HARRINGTON DIR - - - 1997-02-12 15:33:28 - - * PICS DIR - - - 2000-10-12 15:43:23 - - * SYSFILE DIR - - - 2000-07-20 17:48:01 - - * WELCNVT EXEC V 72 9 1 1999-09-20 17:16:18 - - * WELCOME EREADME F 80 21 1 1999-12-27 16:19:00 - - * WELCOME README V 82 21 1 1999-12-27 16:19:04 - - * README ANONYMOU V 71 26 1 1997-04-02 12:33:20 TCP291 - * README ANONYOLD V 71 15 1 1995-08-25 16:04:27 TCP291 - */ - if (numtoks >= 7 && (toklen[0]+toklen[1]) <= 16) - { - for (pos = 1; !lstyle && (pos+5) < numtoks; pos++) - { - p = tokens[pos]; - if ((toklen[pos] == 1 && (*p == 'F' || *p == 'V')) || - (toklen[pos] == 3 && *p == 'D' && p[1] == 'I' && p[2] == 'R')) - { - if (toklen[pos+5] == 8 && (tokens[pos+5][2]) == ':' && - (tokens[pos+5][5]) == ':' ) - { - p = tokens[pos+4]; - if ((toklen[pos+4] == 10 && p[4] == '-' && p[7] == '-') || - (toklen[pos+4] >= 7 && toklen[pos+4] <= 9 && - p[((p[1]!='/')?(2):(1))] == '/' && - p[((p[1]!='/')?(5):(4))] == '/')) - /* Y2K bugs possible ("7/06/102" or "13/02/101") */ - { - if ( (*tokens[pos+1] == '-' && - *tokens[pos+2] == '-' && - *tokens[pos+3] == '-') || - (isASCIIDigit(*tokens[pos+1]) && - isASCIIDigit(*tokens[pos+2]) && - isASCIIDigit(*tokens[pos+3])) ) - { - lstyle = 'C'; - tokmarker = pos; - } - } - } - } - } /* for (pos = 1; !lstyle && (pos+5) < numtoks; pos++) */ - } /* if (numtoks >= 7) */ - - /* extra checking if first pass */ - if (lstyle && !state.listStyle) - { - for (pos = 0, p = tokens[0]; lstyle && pos < toklen[0]; pos++, p++) - { - if (isASCIIAlpha(*p) && toASCIIUpper(*p) != *p) - lstyle = 0; - } - for (pos = tokmarker+1; pos <= tokmarker+3; pos++) - { - if (!(toklen[pos] == 1 && *tokens[pos] == '-')) - { - for (p = tokens[pos]; lstyle && p<(tokens[pos]+toklen[pos]); p++) - { - if (!isASCIIDigit(*p)) - lstyle = 0; - } - } - } - for (pos = 0, p = tokens[tokmarker+4]; - lstyle && pos < toklen[tokmarker+4]; pos++, p++) - { - if (*p == '/') - { - /* There may be Y2K bugs in the date. Don't simplify to - * pos != (len-3) && pos != (len-6) like time is done. - */ - if ((tokens[tokmarker+4][1]) == '/') - { - if (pos != 1 && pos != 4) - lstyle = 0; - } - else if (pos != 2 && pos != 5) - lstyle = 0; - } - else if (*p != '-' && !isASCIIDigit(*p)) - lstyle = 0; - else if (*p == '-' && pos != 4 && pos != 7) - lstyle = 0; - } - for (pos = 0, p = tokens[tokmarker+5]; - lstyle && pos < toklen[tokmarker+5]; pos++, p++) - { - if (*p != ':' && !isASCIIDigit(*p)) - lstyle = 0; - else if (*p == ':' && pos != (toklen[tokmarker+5]-3) - && pos != (toklen[tokmarker+5]-6)) - lstyle = 0; - } - } /* initial if() */ - - if (lstyle == 'C') - { - state.parsedOne = true; - state.listStyle = lstyle; - - p = tokens[tokmarker+4]; - if (toklen[tokmarker+4] == 10) /* newstyle: YYYY-MM-DD format */ - { - result.modifiedTime.tm_year = atoi(p+0) - 1900; - result.modifiedTime.tm_mon = atoi(p+5) - 1; - result.modifiedTime.tm_mday = atoi(p+8); - } - else /* oldstyle: [M]M/DD/YY format */ - { - pos = toklen[tokmarker+4]; - result.modifiedTime.tm_mon = atoi(p) - 1; - result.modifiedTime.tm_mday = atoi((p+pos)-5); - result.modifiedTime.tm_year = atoi((p+pos)-2); - if (result.modifiedTime.tm_year < 70) - result.modifiedTime.tm_year += 100; - } - - p = tokens[tokmarker+5]; - pos = toklen[tokmarker+5]; - result.modifiedTime.tm_hour = atoi(p); - result.modifiedTime.tm_min = atoi((p+pos)-5); - result.modifiedTime.tm_sec = atoi((p+pos)-2); - - result.caseSensitive = true; - result.filename = tokens[0]; - result.filenameLength = toklen[0]; - result.type = FTPFileEntry; - - p = tokens[tokmarker]; - if (toklen[tokmarker] == 3 && *p=='D' && p[1]=='I' && p[2]=='R') - result.type = FTPDirectoryEntry; - - if ((/*newstyle*/ toklen[tokmarker+4] == 10 && tokmarker > 1) || - (/*oldstyle*/ toklen[tokmarker+4] != 10 && tokmarker > 2)) - { /* have a filetype column */ - char *dot; - p = &(tokens[0][toklen[0]]); - memcpy( &dot, &p, sizeof(dot) ); /* NASTY! */ - *dot++ = '.'; - p = tokens[1]; - for (pos = 0; pos < toklen[1]; pos++) - *dot++ = *p++; - result.filenameLength += 1 + toklen[1]; - } - - /* oldstyle LISTING: - * files/dirs not on the 'A' minidisk are not RETRievable/CHDIRable - if (toklen[tokmarker+4] != 10 && *tokens[tokmarker-1] != 'A') - return FTPJunkEntry; - */ - - /* VM/CMS LISTings have no usable filesize field. - * Have to use the 'SIZE' command for that. - */ - return result.type; - - } /* if (lstyle == 'C' && (!state.listStyle || state.listStyle == lstyle)) */ - } /* VM/CMS */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_DOS) /* WinNT DOS dirstyle */ - if (!lstyle && (!state.listStyle || state.listStyle == 'W')) - { - /* - * "10-23-00 01:27PM <DIR> veronist" - * "06-15-00 07:37AM <DIR> zoe" - * "07-14-00 01:35PM 2094926 canprankdesk.tif" - * "07-21-00 01:19PM 95077 Jon Kauffman Enjoys the Good Life.jpg" - * "07-21-00 01:19PM 52275 Name Plate.jpg" - * "07-14-00 01:38PM 2250540 Valentineoffprank-HiRes.jpg" - */ - if ((numtoks >= 4) && toklen[0] == 8 && toklen[1] == 7 && - (*tokens[2] == '<' || isASCIIDigit(*tokens[2])) ) - { - p = tokens[0]; - if ( isASCIIDigit(p[0]) && isASCIIDigit(p[1]) && p[2]=='-' && - isASCIIDigit(p[3]) && isASCIIDigit(p[4]) && p[5]=='-' && - isASCIIDigit(p[6]) && isASCIIDigit(p[7]) ) - { - p = tokens[1]; - if ( isASCIIDigit(p[0]) && isASCIIDigit(p[1]) && p[2]==':' && - isASCIIDigit(p[3]) && isASCIIDigit(p[4]) && - (p[5]=='A' || p[5]=='P') && p[6]=='M') - { - lstyle = 'W'; - if (!state.listStyle) - { - p = tokens[2]; - /* <DIR> or <JUNCTION> */ - if (*p != '<' || p[toklen[2]-1] != '>') - { - for (pos = 1; (lstyle && pos < toklen[2]); pos++) - { - if (!isASCIIDigit(*++p)) - lstyle = 0; - } - } - } - } - } - } - - if (lstyle == 'W') - { - state.parsedOne = true; - state.listStyle = lstyle; - - p = &(line[linelen_sans_wsp]); /* line end sans wsp */ - result.caseSensitive = true; - result.filename = tokens[3]; - result.filenameLength = p - tokens[3]; - result.type = FTPDirectoryEntry; - - if (*tokens[2] != '<') /* not <DIR> or <JUNCTION> */ - { - result.type = FTPFileEntry; - pos = toklen[2]; - result.fileSize = String(tokens[2], pos); - } - else if ((tokens[2][1]) != 'D') /* not <DIR> */ - { - result.type = FTPJunkEntry; /* unknown until junc for sure */ - if (result.filenameLength > 4) - { - p = result.filename; - for (pos = result.filenameLength - 4; pos > 0; pos--) - { - if (p[0] == ' ' && p[3] == ' ' && p[2] == '>' && - (p[1] == '=' || p[1] == '-')) - { - result.type = FTPLinkEntry; - result.filenameLength = p - result.filename; - result.linkname = p + 4; - result.linknameLength = &(line[linelen_sans_wsp]) - - result.linkname; - break; - } - p++; - } - } - } - - result.modifiedTime.tm_mon = atoi(tokens[0]+0); - if (result.modifiedTime.tm_mon != 0) - { - result.modifiedTime.tm_mon--; - result.modifiedTime.tm_mday = atoi(tokens[0]+3); - result.modifiedTime.tm_year = atoi(tokens[0]+6); - if (result.modifiedTime.tm_year < 80) - result.modifiedTime.tm_year += 100; - } - - result.modifiedTime.tm_hour = atoi(tokens[1]+0); - result.modifiedTime.tm_min = atoi(tokens[1]+3); - if ((tokens[1][5]) == 'P' && result.modifiedTime.tm_hour < 12) - result.modifiedTime.tm_hour += 12; - - /* the caller should do this (if dropping "." and ".." is desired) - if (result.type == FTPDirectoryEntry && result.filename[0] == '.' && - (result.filenameLength == 1 || (result.filenameLength == 2 && - result.filename[1] == '.'))) - return FTPJunkEntry; - */ - - return result.type; - } /* if (lstyle == 'W' && (!state.listStyle || state.listStyle == lstyle)) */ - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'W')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_OS2) - if (!lstyle && (!state.listStyle || state.listStyle == 'O')) /* OS/2 test */ - { - /* 220 server IBM TCP/IP for OS/2 - FTP Server ver 23:04:36 on Jan 15 1997 ready. - * fixed position, space padded columns. I have only a vague idea - * of what the contents between col 18 and 34 might be: All I can infer - * is that there may be attribute flags in there and there may be - * a " DIR" in there. - * - * 1 2 3 4 5 6 - *0123456789012345678901234567890123456789012345678901234567890123456789 - *----- size -------|??????????????? MM-DD-YY| HH:MM| nnnnnnnnn.... - * 0 DIR 04-11-95 16:26 . - * 0 DIR 04-11-95 16:26 .. - * 0 DIR 04-11-95 16:26 ADDRESS - * 612 RHSA 07-28-95 16:45 air_tra1.bag - * 195 A 08-09-95 10:23 Alfa1.bag - * 0 RHS DIR 04-11-95 16:26 ATTACH - * 372 A 08-09-95 10:26 Aussie_1.bag - * 310992 06-28-94 09:56 INSTALL.EXE - * 1 2 3 4 - * 01234567890123456789012345678901234567890123456789 - * dirlist from the mirror.pl project, col positions from Mozilla. - */ - p = &(line[toklen[0]]); - /* \s(\d\d-\d\d-\d\d)\s+(\d\d:\d\d)\s */ - if (numtoks >= 4 && toklen[0] <= 18 && isASCIIDigit(*tokens[0]) && - (linelen - toklen[0]) >= (53-18) && - p[18-18] == ' ' && p[34-18] == ' ' && - p[37-18] == '-' && p[40-18] == '-' && p[43-18] == ' ' && - p[45-18] == ' ' && p[48-18] == ':' && p[51-18] == ' ' && - isASCIIDigit(p[35-18]) && isASCIIDigit(p[36-18]) && - isASCIIDigit(p[38-18]) && isASCIIDigit(p[39-18]) && - isASCIIDigit(p[41-18]) && isASCIIDigit(p[42-18]) && - isASCIIDigit(p[46-18]) && isASCIIDigit(p[47-18]) && - isASCIIDigit(p[49-18]) && isASCIIDigit(p[50-18]) - ) - { - lstyle = 'O'; /* OS/2 */ - if (!state.listStyle) - { - for (pos = 1; lstyle && pos < toklen[0]; pos++) - { - if (!isASCIIDigit(tokens[0][pos])) - lstyle = 0; - } - } - } - - if (lstyle == 'O') - { - state.parsedOne = true; - state.listStyle = lstyle; - - p = &(line[toklen[0]]); - - result.caseSensitive = true; - result.filename = &p[53-18]; - result.filenameLength = (&(line[linelen_sans_wsp])) - - (result.filename); - result.type = FTPFileEntry; - - /* I don't have a real listing to determine exact pos, so scan. */ - for (pos = (18-18); pos < ((35-18)-4); pos++) - { - if (p[pos+0] == ' ' && p[pos+1] == 'D' && - p[pos+2] == 'I' && p[pos+3] == 'R') - { - result.type = FTPDirectoryEntry; - break; - } - } - - if (result.type != FTPDirectoryEntry) - { - pos = toklen[0]; - result.fileSize = String(tokens[0], pos); - } - - result.modifiedTime.tm_mon = atoi(&p[35-18]) - 1; - result.modifiedTime.tm_mday = atoi(&p[38-18]); - result.modifiedTime.tm_year = atoi(&p[41-18]); - if (result.modifiedTime.tm_year < 80) - result.modifiedTime.tm_year += 100; - result.modifiedTime.tm_hour = atoi(&p[46-18]); - result.modifiedTime.tm_min = atoi(&p[49-18]); - - /* the caller should do this (if dropping "." and ".." is desired) - if (result.type == FTPDirectoryEntry && result.filename[0] == '.' && - (result.filenameLength == 1 || (result.filenameLength == 2 && - result.filename[1] == '.'))) - return FTPJunkEntry; - */ - - return result.type; - } /* if (lstyle == 'O') */ - - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'O')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_LSL) - if (!lstyle && (!state.listStyle || state.listStyle == 'U')) /* /bin/ls & co. */ - { - /* UNIX-style listing, without inum and without blocks - * "-rw-r--r-- 1 root other 531 Jan 29 03:26 README" - * "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc" - * "dr-xr-xr-x 2 root 512 Apr 8 1994 etc" - * "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin" - * Also produced by Microsoft's FTP servers for Windows: - * "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z" - * "d--------- 1 owner group 0 May 9 19:45 Softlib" - * Also WFTPD for MSDOS: - * "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp" - * Hellsoft for NetWare: - * "d[RWCEMFA] supervisor 512 Jan 16 18:53 login" - * "-[RWCEMFA] rhesus 214059 Oct 20 15:27 cx.exe" - * Newer Hellsoft for NetWare: (netlab2.usu.edu) - * - [RWCEAFMS] NFAUUser 192 Apr 27 15:21 HEADER.html - * d [RWCEAFMS] jrd 512 Jul 11 03:01 allupdates - * Also NetPresenz for the Mac: - * "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit" - * "drwxrwxr-x folder 2 May 10 1996 network" - * Protected directory: - * "drwx-wx-wt 2 root wheel 512 Jul 1 02:15 incoming" - * uid/gid instead of username/groupname: - * "drwxr-xr-x 2 0 0 512 May 28 22:17 etc" - */ - - if (numtoks >= 6) - { - /* there are two perm formats (Hellsoft/NetWare and *IX strmode(3)). - * Scan for size column only if the perm format is one or the other. - */ - if (toklen[0] == 1 || (tokens[0][1]) == '[') - { - if (*tokens[0] == 'd' || *tokens[0] == '-') - { - pos = toklen[0]-1; - p = tokens[0] + 1; - if (pos == 0) - { - p = tokens[1]; - pos = toklen[1]; - } - if ((pos == 9 || pos == 10) && - (*p == '[' && p[pos-1] == ']') && - (p[1] == 'R' || p[1] == '-') && - (p[2] == 'W' || p[2] == '-') && - (p[3] == 'C' || p[3] == '-') && - (p[4] == 'E' || p[4] == '-')) - { - /* rest is FMA[S] or AFM[S] */ - lstyle = 'U'; /* very likely one of the NetWare servers */ - } - } - } - else if ((toklen[0] == 10 || toklen[0] == 11) - && strchr("-bcdlpsw?DFam", *tokens[0])) - { - p = &(tokens[0][1]); - if ((p[0] == 'r' || p[0] == '-') && - (p[1] == 'w' || p[1] == '-') && - (p[3] == 'r' || p[3] == '-') && - (p[4] == 'w' || p[4] == '-') && - (p[6] == 'r' || p[6] == '-') && - (p[7] == 'w' || p[7] == '-')) - /* 'x'/p[9] can be S|s|x|-|T|t or implementation specific */ - { - lstyle = 'U'; /* very likely /bin/ls */ - } - } - } - if (lstyle == 'U') /* first token checks out */ - { - lstyle = 0; - for (pos = (numtoks-5); !lstyle && pos > 1; pos--) - { - /* scan for: (\d+)\s+([A-Z][a-z][a-z])\s+ - * (\d\d\d\d|\d\:\d\d|\d\d\:\d\d|\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d) - * \s+(.+)$ - */ - if (isASCIIDigit(*tokens[pos]) /* size */ - /* (\w\w\w) */ - && toklen[pos+1] == 3 && isASCIIAlpha(*tokens[pos+1]) && - isASCIIAlpha(tokens[pos+1][1]) && isASCIIAlpha(tokens[pos+1][2]) - /* (\d|\d\d) */ - && isASCIIDigit(*tokens[pos+2]) && - (toklen[pos+2] == 1 || - (toklen[pos+2] == 2 && isASCIIDigit(tokens[pos+2][1]))) - && toklen[pos+3] >= 4 && isASCIIDigit(*tokens[pos+3]) - /* (\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d) */ - && (toklen[pos+3] <= 5 || ( - (toklen[pos+3] == 7 || toklen[pos+3] == 8) && - (tokens[pos+3][toklen[pos+3]-3]) == ':')) - && isASCIIDigit(tokens[pos+3][toklen[pos+3]-2]) - && isASCIIDigit(tokens[pos+3][toklen[pos+3]-1]) - && ( - /* (\d\d\d\d) */ - ((toklen[pos+3] == 4 || toklen[pos+3] == 5) && - isASCIIDigit(tokens[pos+3][1]) && - isASCIIDigit(tokens[pos+3][2]) ) - /* (\d\:\d\d|\d\:\d\d\:\d\d) */ - || ((toklen[pos+3] == 4 || toklen[pos+3] == 7) && - (tokens[pos+3][1]) == ':' && - isASCIIDigit(tokens[pos+3][2]) && isASCIIDigit(tokens[pos+3][3])) - /* (\d\d\:\d\d|\d\d\:\d\d\:\d\d) */ - || ((toklen[pos+3] == 5 || toklen[pos+3] == 8) && - isASCIIDigit(tokens[pos+3][1]) && (tokens[pos+3][2]) == ':' && - isASCIIDigit(tokens[pos+3][3]) && isASCIIDigit(tokens[pos+3][4])) - ) - ) - { - lstyle = 'U'; /* assume /bin/ls or variant format */ - tokmarker = pos; - - /* check that size is numeric */ - p = tokens[tokmarker]; - for (pos = 0; lstyle && pos < toklen[tokmarker]; pos++) - { - if (!isASCIIDigit(*p++)) - lstyle = 0; - } - if (lstyle) - { - month_num = 0; - p = tokens[tokmarker+1]; - for (pos = 0;pos < (12*3); pos+=3) - { - if (p[0] == month_names[pos+0] && - p[1] == month_names[pos+1] && - p[2] == month_names[pos+2]) - break; - month_num++; - } - if (month_num >= 12) - lstyle = 0; - } - } /* relative position test */ - } /* while (pos+5) < numtoks */ - } /* if (numtoks >= 4) */ - - if (lstyle == 'U') - { - state.parsedOne = true; - state.listStyle = lstyle; - - result.caseSensitive = false; - result.type = FTPJunkEntry; - if (*tokens[0] == 'd' || *tokens[0] == 'D') - result.type = FTPDirectoryEntry; - else if (*tokens[0] == 'l') - result.type = FTPLinkEntry; - else if (*tokens[0] == '-' || *tokens[0] == 'F') - result.type = FTPFileEntry; /* (hopefully a regular file) */ - - if (result.type != FTPDirectoryEntry) - { - pos = toklen[tokmarker]; - result.fileSize = String(tokens[tokmarker], pos); - } - - result.modifiedTime.tm_mon = month_num; - result.modifiedTime.tm_mday = atoi(tokens[tokmarker+2]); - if (result.modifiedTime.tm_mday == 0) - result.modifiedTime.tm_mday++; - - p = tokens[tokmarker+3]; - pos = (unsigned int)atoi(p); - if (p[1] == ':') /* one digit hour */ - p--; - if (p[2] != ':') /* year */ - { - result.modifiedTime.tm_year = pos; - } - else - { - result.modifiedTime.tm_hour = pos; - result.modifiedTime.tm_min = atoi(p+3); - if (p[5] == ':') - result.modifiedTime.tm_sec = atoi(p+6); - - if (!state.now) - { - time_t now = time(NULL); - state.now = now * 1000000.0; - - // FIXME: This code has the year 2038 bug - gmtime_r(&now, &state.nowFTPTime); - state.nowFTPTime.tm_year += 1900; - } - - result.modifiedTime.tm_year = state.nowFTPTime.tm_year; - if ( (( state.nowFTPTime.tm_mon << 5) + state.nowFTPTime.tm_mday) < - ((result.modifiedTime.tm_mon << 5) + result.modifiedTime.tm_mday) ) - result.modifiedTime.tm_year--; - - } /* time/year */ - - result.filename = tokens[tokmarker+4]; - result.filenameLength = (&(line[linelen_sans_wsp])) - - (result.filename); - - if (result.type == FTPLinkEntry && result.filenameLength > 4) - { - p = result.filename + 1; - for (pos = 1; pos < (result.filenameLength - 4); pos++) - { - if (*p == ' ' && p[1] == '-' && p[2] == '>' && p[3] == ' ') - { - result.linkname = p + 4; - result.linknameLength = (&(line[linelen_sans_wsp])) - - (result.linkname); - result.filenameLength = pos; - break; - } - p++; - } - } - -#if defined(SUPPORT_LSLF) /* some (very rare) servers return ls -lF */ - if (result.filenameLength > 1) - { - p = result.filename[result.filenameLength-1]; - pos = result.type; - if (pos == 'd') { - if (*p == '/') result.filenameLength--; /* directory */ - } else if (pos == 'l') { - if (*p == '@') result.filenameLength--; /* symlink */ - } else if (pos == 'f') { - if (*p == '*') result.filenameLength--; /* executable */ - } else if (*p == '=' || *p == '%' || *p == '|') { - result.filenameLength--; /* socket, whiteout, fifo */ - } - } -#endif - - /* the caller should do this (if dropping "." and ".." is desired) - if (result.type == FTPDirectoryEntry && result.filename[0] == '.' && - (result.filenameLength == 1 || (result.filenameLength == 2 && - result.filename[1] == '.'))) - return FTPJunkEntry; - */ - - return result.type; - - } /* if (lstyle == 'U') */ - - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'U')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_W16) /* 16bit Windows */ - if (!lstyle && (!state.listStyle || state.listStyle == 'w')) - { /* old SuperTCP suite FTP server for Win3.1 */ - /* old NetManage Chameleon TCP/IP suite FTP server for Win3.1 */ - /* - * SuperTCP dirlist from the mirror.pl project - * mon/day/year separator may be '/' or '-'. - * . <DIR> 11-16-94 17:16 - * .. <DIR> 11-16-94 17:16 - * INSTALL <DIR> 11-16-94 17:17 - * CMT <DIR> 11-21-94 10:17 - * DESIGN1.DOC 11264 05-11-95 14:20 - * README.TXT 1045 05-10-95 11:01 - * WPKIT1.EXE 960338 06-21-95 17:01 - * CMT.CSV 0 07-06-95 14:56 - * - * Chameleon dirlist guessed from lynx - * . <DIR> Nov 16 1994 17:16 - * .. <DIR> Nov 16 1994 17:16 - * INSTALL <DIR> Nov 16 1994 17:17 - * CMT <DIR> Nov 21 1994 10:17 - * DESIGN1.DOC 11264 May 11 1995 14:20 A - * README.TXT 1045 May 10 1995 11:01 - * WPKIT1.EXE 960338 Jun 21 1995 17:01 R - * CMT.CSV 0 Jul 06 1995 14:56 RHA - */ - if (numtoks >= 4 && toklen[0] < 13 && - ((toklen[1] == 5 && *tokens[1] == '<') || isASCIIDigit(*tokens[1])) ) - { - if (numtoks == 4 - && (toklen[2] == 8 || toklen[2] == 9) - && (((tokens[2][2]) == '/' && (tokens[2][5]) == '/') || - ((tokens[2][2]) == '-' && (tokens[2][5]) == '-')) - && (toklen[3] == 4 || toklen[3] == 5) - && (tokens[3][toklen[3]-3]) == ':' - && isASCIIDigit(tokens[2][0]) && isASCIIDigit(tokens[2][1]) - && isASCIIDigit(tokens[2][3]) && isASCIIDigit(tokens[2][4]) - && isASCIIDigit(tokens[2][6]) && isASCIIDigit(tokens[2][7]) - && (toklen[2] < 9 || isASCIIDigit(tokens[2][8])) - && isASCIIDigit(tokens[3][toklen[3]-1]) && isASCIIDigit(tokens[3][toklen[3]-2]) - && isASCIIDigit(tokens[3][toklen[3]-4]) && isASCIIDigit(*tokens[3]) - ) - { - lstyle = 'w'; - } - else if ((numtoks == 6 || numtoks == 7) - && toklen[2] == 3 && toklen[3] == 2 - && toklen[4] == 4 && toklen[5] == 5 - && (tokens[5][2]) == ':' - && isASCIIAlpha(tokens[2][0]) && isASCIIAlpha(tokens[2][1]) - && isASCIIAlpha(tokens[2][2]) - && isASCIIDigit(tokens[3][0]) && isASCIIDigit(tokens[3][1]) - && isASCIIDigit(tokens[4][0]) && isASCIIDigit(tokens[4][1]) - && isASCIIDigit(tokens[4][2]) && isASCIIDigit(tokens[4][3]) - && isASCIIDigit(tokens[5][0]) && isASCIIDigit(tokens[5][1]) - && isASCIIDigit(tokens[5][3]) && isASCIIDigit(tokens[5][4]) - /* could also check that (&(tokens[5][5]) - tokens[2]) == 17 */ - ) - { - lstyle = 'w'; - } - if (lstyle && state.listStyle != lstyle) /* first time */ - { - p = tokens[1]; - if (toklen[1] != 5 || p[0] != '<' || p[1] != 'D' || - p[2] != 'I' || p[3] != 'R' || p[4] != '>') - { - for (pos = 0; lstyle && pos < toklen[1]; pos++) - { - if (!isASCIIDigit(*p++)) - lstyle = 0; - } - } /* not <DIR> */ - } /* if (first time) */ - } /* if (numtoks == ...) */ - - if (lstyle == 'w') - { - state.parsedOne = true; - state.listStyle = lstyle; - - result.caseSensitive = true; - result.filename = tokens[0]; - result.filenameLength = toklen[0]; - result.type = FTPDirectoryEntry; - - p = tokens[1]; - if (isASCIIDigit(*p)) - { - result.type = FTPFileEntry; - pos = toklen[1]; - result.fileSize = String(p, pos); - } - - p = tokens[2]; - if (toklen[2] == 3) /* Chameleon */ - { - tbuf[0] = toASCIIUpper(p[0]); - tbuf[1] = toASCIILower(p[1]); - tbuf[2] = toASCIILower(p[2]); - for (pos = 0; pos < (12*3); pos+=3) - { - if (tbuf[0] == month_names[pos+0] && - tbuf[1] == month_names[pos+1] && - tbuf[2] == month_names[pos+2]) - { - result.modifiedTime.tm_mon = pos/3; - result.modifiedTime.tm_mday = atoi(tokens[3]); - result.modifiedTime.tm_year = atoi(tokens[4]) - 1900; - break; - } - } - pos = 5; /* Chameleon toknum of date field */ - } - else - { - result.modifiedTime.tm_mon = atoi(p+0)-1; - result.modifiedTime.tm_mday = atoi(p+3); - result.modifiedTime.tm_year = atoi(p+6); - if (result.modifiedTime.tm_year < 80) /* SuperTCP */ - result.modifiedTime.tm_year += 100; - - pos = 3; /* SuperTCP toknum of date field */ - } - - result.modifiedTime.tm_hour = atoi(tokens[pos]); - result.modifiedTime.tm_min = atoi(&(tokens[pos][toklen[pos]-2])); - - /* the caller should do this (if dropping "." and ".." is desired) - if (result.type == FTPDirectoryEntry && result.filename[0] == '.' && - (result.filenameLength == 1 || (result.filenameLength == 2 && - result.filename[1] == '.'))) - return FTPJunkEntry; - */ - - return result.type; - } /* (lstyle == 'w') */ - - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'w')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - -#if defined(SUPPORT_DLS) /* dls -dtR */ - if (!lstyle && - (state.listStyle == 'D' || (!state.listStyle && state.numLines == 1))) - /* /bin/dls lines have to be immediately recognizable (first line) */ - { - /* I haven't seen an FTP server that delivers a /bin/dls listing, - * but can infer the format from the lynx and mirror.pl projects. - * Both formats are supported. - * - * Lynx says: - * README 763 Information about this server\0 - * bin/ - \0 - * etc/ = \0 - * ls-lR 0 \0 - * ls-lR.Z 3 \0 - * pub/ = Public area\0 - * usr/ - \0 - * morgan 14 -> ../real/morgan\0 - * TIMIT.mostlikely.Z\0 - * 79215 \0 - * - * mirror.pl says: - * filename: ^(\S*)\s+ - * size: (\-|\=|\d+)\s+ - * month/day: ((\w\w\w\s+\d+|\d+\s+\w\w\w)\s+ - * time/year: (\d+:\d+|\d\d\d\d))\s+ - * rest: (.+) - * - * README 763 Jul 11 21:05 Information about this server - * bin/ - Apr 28 1994 - * etc/ = 11 Jul 21:04 - * ls-lR 0 6 Aug 17:14 - * ls-lR.Z 3 05 Sep 1994 - * pub/ = Jul 11 21:04 Public area - * usr/ - Sep 7 09:39 - * morgan 14 Apr 18 09:39 -> ../real/morgan - * TIMIT.mostlikely.Z - * 79215 Jul 11 21:04 - */ - if (!state.listStyle && line[linelen-1] == ':' && - linelen >= 2 && toklen[numtoks-1] != 1) - { - /* code in mirror.pl suggests that a listing may be preceded - * by a PWD line in the form "/some/dir/names/here:" - * but does not necessarily begin with '/'. *sigh* - */ - pos = 0; - p = line; - while (pos < (linelen-1)) - { - /* illegal (or extremely unusual) chars in a dirspec */ - if (*p == '<' || *p == '|' || *p == '>' || - *p == '?' || *p == '*' || *p == '\\') - break; - if (*p == '/' && pos < (linelen-2) && p[1] == '/') - break; - pos++; - p++; - } - if (pos == (linelen-1)) - { - state.listStyle = 'D'; - return FTPJunkEntry; - } - } - - if (!lstyle && numtoks >= 2) - { - pos = 22; /* pos of (\d+|-|=) if this is not part of a multiline */ - if (state.listStyle && carry_buf_len) /* first is from previous line */ - pos = toklen[1]-1; /* and is 'as-is' (may contain whitespace) */ - - if (linelen > pos) - { - p = &line[pos]; - if ((*p == '-' || *p == '=' || isASCIIDigit(*p)) && - ((linelen == (pos+1)) || - (linelen >= (pos+3) && p[1] == ' ' && p[2] == ' ')) ) - { - tokmarker = 1; - if (!carry_buf_len) - { - pos = 1; - while (pos < numtoks && (tokens[pos]+toklen[pos]) < (&line[23])) - pos++; - tokmarker = 0; - if ((tokens[pos]+toklen[pos]) == (&line[23])) - tokmarker = pos; - } - if (tokmarker) - { - lstyle = 'D'; - if (*tokens[tokmarker] == '-' || *tokens[tokmarker] == '=') - { - if (toklen[tokmarker] != 1 || - (tokens[tokmarker-1][toklen[tokmarker-1]-1]) != '/') - lstyle = 0; - } - else - { - for (pos = 0; lstyle && pos < toklen[tokmarker]; pos++) - { - if (!isASCIIDigit(tokens[tokmarker][pos])) - lstyle = 0; - } - } - if (lstyle && !state.listStyle) /* first time */ - { - /* scan for illegal (or incredibly unusual) chars in fname */ - for (p = tokens[0]; lstyle && - p < &(tokens[tokmarker-1][toklen[tokmarker-1]]); p++) - { - if (*p == '<' || *p == '|' || *p == '>' || - *p == '?' || *p == '*' || *p == '/' || *p == '\\') - lstyle = 0; - } - } - - } /* size token found */ - } /* expected chars behind expected size token */ - } /* if (linelen > pos) */ - } /* if (!lstyle && numtoks >= 2) */ - - if (!lstyle && state.listStyle == 'D' && !carry_buf_len) - { - /* the filename of a multi-line entry can be identified - * correctly only if dls format had been previously established. - * This should always be true because there should be entries - * for '.' and/or '..' and/or CWD that precede the rest of the - * listing. - */ - pos = linelen; - if (pos > (sizeof(state.carryBuffer)-1)) - pos = sizeof(state.carryBuffer)-1; - memcpy( state.carryBuffer, line, pos ); - state.carryBufferLength = pos; - return FTPJunkEntry; - } - - if (lstyle == 'D') - { - state.parsedOne = true; - state.listStyle = lstyle; - - p = &(tokens[tokmarker-1][toklen[tokmarker-1]]); - result.filename = tokens[0]; - result.filenameLength = p - tokens[0]; - result.type = FTPFileEntry; - - if (result.filename[result.filenameLength-1] == '/') - { - if (result.linknameLength == 1) - result.type = FTPJunkEntry; - else - { - result.filenameLength--; - result.type = FTPDirectoryEntry; - } - } - else if (isASCIIDigit(*tokens[tokmarker])) - { - pos = toklen[tokmarker]; - result.fileSize = String(tokens[tokmarker], pos); - } - - if ((tokmarker+3) < numtoks && - (&(tokens[numtoks-1][toklen[numtoks-1]]) - - tokens[tokmarker+1]) >= (1+1+3+1+4) ) - { - pos = (tokmarker+3); - p = tokens[pos]; - pos = toklen[pos]; - - if ((pos == 4 || pos == 5) - && isASCIIDigit(*p) && isASCIIDigit(p[pos-1]) && isASCIIDigit(p[pos-2]) - && ((pos == 5 && p[2] == ':') || - (pos == 4 && (isASCIIDigit(p[1]) || p[1] == ':'))) - ) - { - month_num = tokmarker+1; /* assumed position of month field */ - pos = tokmarker+2; /* assumed position of mday field */ - if (isASCIIDigit(*tokens[month_num])) /* positions are reversed */ - { - month_num++; - pos--; - } - p = tokens[month_num]; - if (isASCIIDigit(*tokens[pos]) - && (toklen[pos] == 1 || - (toklen[pos] == 2 && isASCIIDigit(tokens[pos][1]))) - && toklen[month_num] == 3 - && isASCIIAlpha(*p) && isASCIIAlpha(p[1]) && isASCIIAlpha(p[2]) ) - { - pos = atoi(tokens[pos]); - if (pos > 0 && pos <= 31) - { - result.modifiedTime.tm_mday = pos; - month_num = 1; - for (pos = 0; pos < (12*3); pos+=3) - { - if (p[0] == month_names[pos+0] && - p[1] == month_names[pos+1] && - p[2] == month_names[pos+2]) - break; - month_num++; - } - if (month_num > 12) - result.modifiedTime.tm_mday = 0; - else - result.modifiedTime.tm_mon = month_num - 1; - } - } - if (result.modifiedTime.tm_mday) - { - tokmarker += 3; /* skip mday/mon/yrtime (to find " -> ") */ - p = tokens[tokmarker]; - - pos = atoi(p); - if (pos > 24) - result.modifiedTime.tm_year = pos-1900; - else - { - if (p[1] == ':') - p--; - result.modifiedTime.tm_hour = pos; - result.modifiedTime.tm_min = atoi(p+3); - if (!state.now) - { - time_t now = time(NULL); - state.now = now * 1000000.0; - - // FIXME: This code has the year 2038 bug - gmtime_r(&now, &state.nowFTPTime); - state.nowFTPTime.tm_year += 1900; - } - result.modifiedTime.tm_year = state.nowFTPTime.tm_year; - if ( (( state.nowFTPTime.tm_mon << 4) + state.nowFTPTime.tm_mday) < - ((result.modifiedTime.tm_mon << 4) + result.modifiedTime.tm_mday) ) - result.modifiedTime.tm_year--; - } /* got year or time */ - } /* got month/mday */ - } /* may have year or time */ - } /* enough remaining to possibly have date/time */ - - if (numtoks > (tokmarker+2)) - { - pos = tokmarker+1; - p = tokens[pos]; - if (toklen[pos] == 2 && *p == '-' && p[1] == '>') - { - p = &(tokens[numtoks-1][toklen[numtoks-1]]); - result.type = FTPLinkEntry; - result.linkname = tokens[pos+1]; - result.linknameLength = p - result.linkname; - if (result.linknameLength > 1 && - result.linkname[result.linknameLength-1] == '/') - result.linknameLength--; - } - } /* if (numtoks > (tokmarker+2)) */ - - /* the caller should do this (if dropping "." and ".." is desired) - if (result.type == FTPDirectoryEntry && result.filename[0] == '.' && - (result.filenameLength == 1 || (result.filenameLength == 2 && - result.filename[1] == '.'))) - return FTPJunkEntry; - */ - - return result.type; - - } /* if (lstyle == 'D') */ - } /* if (!lstyle && (!state.listStyle || state.listStyle == 'D')) */ -#endif - - /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ - - } /* if (linelen > 0) */ - - if (state.parsedOne || state.listStyle) /* junk if we fail to parse */ - return FTPJunkEntry; /* this time but had previously parsed sucessfully */ - return FTPMiscEntry; /* its part of a comment or error message */ -} - -} // namespace WebCore - -#endif // ENABLE(FTPDIR) diff --git a/WebCore/loader/FTPDirectoryParser.h b/WebCore/loader/FTPDirectoryParser.h deleted file mode 100644 index 023a895..0000000 --- a/WebCore/loader/FTPDirectoryParser.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2002 Cyrus Patel <cyp@fb14.uni-mainz.de> - * (C) 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 Lesser General Public - * License 2.1 as published by the Free Software Foundation. - * - * 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. - */ - -/* ParseFTPList() parses lines from an FTP LIST command. -** -** Written July 2002 by Cyrus Patel <cyp@fb14.uni-mainz.de> -** with acknowledgements to squid, lynx, wget and ftpmirror. -** -** Arguments: -** 'line': line of FTP data connection output. The line is assumed -** to end at the first '\0' or '\n' or '\r\n'. -** 'state': a structure used internally to track state between -** lines. Needs to be bzero()'d at LIST begin. -** 'result': where ParseFTPList will store the results of the parse -** if 'line' is not a comment and is not junk. -** -** Returns one of the following: -** 'd' - LIST line is a directory entry ('result' is valid) -** 'f' - LIST line is a file's entry ('result' is valid) -** 'l' - LIST line is a symlink's entry ('result' is valid) -** '?' - LIST line is junk. (cwd, non-file/dir/link, etc) -** '"' - its not a LIST line (its a "comment") -** -** It may be advisable to let the end-user see "comments" (particularly when -** the listing results in ONLY such lines) because such a listing may be: -** - an unknown LIST format (NLST or "custom" format for example) -** - an error msg (EPERM,ENOENT,ENFILE,EMFILE,ENOTDIR,ENOTBLK,EEXDEV etc). -** - an empty directory and the 'comment' is a "total 0" line or similar. -** (warning: a "total 0" can also mean the total size is unknown). -** -** ParseFTPList() supports all known FTP LISTing formats: -** - '/bin/ls -l' and all variants (including Hellsoft FTP for NetWare); -** - EPLF (Easily Parsable List Format); -** - Windows NT's default "DOS-dirstyle"; -** - OS/2 basic server format LIST format; -** - VMS (MultiNet, UCX, and CMU) LIST format (including multi-line format); -** - IBM VM/CMS, VM/ESA LIST format (two known variants); -** - SuperTCP FTP Server for Win16 LIST format; -** - NetManage Chameleon (NEWT) for Win16 LIST format; -** - '/bin/dls' (two known variants, plus multi-line) LIST format; -** If there are others, then I'd like to hear about them (send me a sample). -** -** NLSTings are not supported explicitely because they cannot be machine -** parsed consistantly: NLSTings do not have unique characteristics - even -** the assumption that there won't be whitespace on the line does not hold -** because some nlistings have more than one filename per line and/or -** may have filenames that have spaces in them. Moreover, distinguishing -** between an error message and an NLST line would require ParseList() to -** recognize all the possible strerror() messages in the world. -*/ - -// This was originally Mozilla code, titled ParseFTPList.h -// Original version of this file can currently be found at: http://mxr.mozilla.org/mozilla1.8/source/netwerk/streamconv/converters/ParseFTPList.h - -#ifndef FTPDirectoryParser_h -#define FTPDirectoryParser_h - -#include "PlatformString.h" - -#include <time.h> - -#define SUPPORT_LSL /* Support for /bin/ls -l and dozens of variations therof */ -#define SUPPORT_DLS /* Support for /bin/dls format (very, Very, VERY rare) */ -#define SUPPORT_EPLF /* Support for Extraordinarily Pathetic List Format */ -#define SUPPORT_DOS /* Support for WinNT server in 'site dirstyle' dos */ -#define SUPPORT_VMS /* Support for VMS (all: MultiNet, UCX, CMU-IP) */ -#define SUPPORT_CMS /* Support for IBM VM/CMS,VM/ESA (z/VM and LISTING forms) */ -#define SUPPORT_OS2 /* Support for IBM TCP/IP for OS/2 - FTP Server */ -#define SUPPORT_W16 /* Support for win16 hosts: SuperTCP or NetManage Chameleon */ - -namespace WebCore { - -typedef struct tm FTPTime; - -struct ListState { - ListState() - : now(0) - , listStyle(0) - , parsedOne(false) - , carryBufferLength(0) - , numLines(0) - { - memset(&nowFTPTime, 0, sizeof(FTPTime)); - } - - double now; /* needed for year determination */ - FTPTime nowFTPTime; - char listStyle; /* LISTing style */ - bool parsedOne; /* returned anything yet? */ - char carryBuffer[84]; /* for VMS multiline */ - int carryBufferLength; /* length of name in carry_buf */ - int64_t numLines; /* number of lines seen */ -}; - -enum FTPEntryType { - FTPDirectoryEntry, - FTPFileEntry, - FTPLinkEntry, - FTPMiscEntry, - FTPJunkEntry -}; - -struct ListResult -{ - ListResult() - { - clear(); - } - - void clear() - { - valid = false; - type = FTPJunkEntry; - filename = 0; - filenameLength = 0; - linkname = 0; - linknameLength = 0; - fileSize.truncate(0); - caseSensitive = false; - memset(&modifiedTime, 0, sizeof(FTPTime)); - } - - bool valid; - FTPEntryType type; - - const char* filename; - uint32_t filenameLength; - - const char* linkname; - uint32_t linknameLength; - - String fileSize; - FTPTime modifiedTime; - bool caseSensitive; // file system is definitely case insensitive -}; - -FTPEntryType parseOneFTPLine(const char* inputLine, ListState&, ListResult&); - -} // namespace WebCore - -#endif // FTPDirectoryParser_h diff --git a/WebCore/loader/FormState.cpp b/WebCore/loader/FormState.cpp deleted file mode 100644 index c55b8ac..0000000 --- a/WebCore/loader/FormState.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FormState.h" - -#include "Frame.h" -#include "HTMLFormElement.h" - -namespace WebCore { - -PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, const HashMap<String, String>& values, PassRefPtr<Frame> sourceFrame) -{ - return adoptRef(new FormState(form, values, sourceFrame)); -} - -FormState::FormState(PassRefPtr<HTMLFormElement> form, const HashMap<String, String>& values, PassRefPtr<Frame> sourceFrame) - : m_form(form) - , m_values(values) - , m_sourceFrame(sourceFrame) -{ -} - -} diff --git a/WebCore/loader/FormState.h b/WebCore/loader/FormState.h deleted file mode 100644 index 5370e8a..0000000 --- a/WebCore/loader/FormState.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FormState_h -#define FormState_h - -#include <wtf/RefCounted.h> -#include "StringHash.h" -#include <wtf/HashMap.h> - -namespace WebCore { - - class Frame; - class HTMLFormElement; - - class FormState : public RefCounted<FormState> { - public: - static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement> form, const HashMap<String, String>& values, PassRefPtr<Frame> sourceFrame); - - HTMLFormElement* form() const { return m_form.get(); } - const HashMap<String, String>& values() const { return m_values; } - Frame* sourceFrame() const { return m_sourceFrame.get(); } - - private: - FormState(PassRefPtr<HTMLFormElement> form, const HashMap<String, String>& values, PassRefPtr<Frame> sourceFrame); - - RefPtr<HTMLFormElement> m_form; - HashMap<String, String> m_values; - RefPtr<Frame> m_sourceFrame; - }; - -} - -#endif // FormState_h diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp deleted file mode 100644 index 0285a8c..0000000 --- a/WebCore/loader/FrameLoader.cpp +++ /dev/null @@ -1,5283 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FrameLoader.h" - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -#include "Archive.h" -#include "ArchiveFactory.h" -#endif -#include "CString.h" -#include "Cache.h" -#include "CachedPage.h" -#include "Chrome.h" -#include "DOMImplementation.h" -#include "DOMWindow.h" -#include "DocLoader.h" -#include "Document.h" -#include "DocumentLoader.h" -#include "Editor.h" -#include "EditorClient.h" -#include "Element.h" -#include "Event.h" -#include "EventNames.h" -#include "FloatRect.h" -#include "FormState.h" -#include "Frame.h" -#include "FrameLoadRequest.h" -#include "FrameLoaderClient.h" -#include "FramePrivate.h" -#include "FrameTree.h" -#include "FrameView.h" -#include "HTMLFormElement.h" -#include "HTMLFrameElement.h" -#include "HTMLNames.h" -#include "HTMLObjectElement.h" -#include "HTTPParsers.h" -#include "HistoryItem.h" -#include "IconDatabase.h" -#include "IconLoader.h" -#include "InspectorController.h" -#include "Logging.h" -#include "MIMETypeRegistry.h" -#include "MainResourceLoader.h" -#include "Page.h" -#include "PageCache.h" -#include "PageGroup.h" -#include "PluginData.h" -#include "ProgressTracker.h" -#include "RenderPart.h" -#include "RenderWidget.h" -#include "RenderView.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "SecurityOrigin.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "SystemTime.h" -#include "TextResourceDecoder.h" -#include "WindowFeatures.h" -#include "XMLHttpRequest.h" -#include "XMLTokenizer.h" -#include "JSDOMBinding.h" -#include "ScriptController.h" -#include <runtime/JSLock.h> -#include <runtime/JSObject.h> - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) -#include "ApplicationCache.h" -#include "ApplicationCacheResource.h" -#endif - -#if ENABLE(SVG) -#include "SVGDocument.h" -#include "SVGLocatable.h" -#include "SVGNames.h" -#include "SVGPreserveAspectRatio.h" -#include "SVGSVGElement.h" -#include "SVGViewElement.h" -#include "SVGViewSpec.h" -#endif - -#ifdef ANDROID_INSTRUMENT -#include "TimeCounter.h" -#endif - -using namespace JSC; - -namespace WebCore { - -#if ENABLE(SVG) -using namespace SVGNames; -#endif -using namespace HTMLNames; - -#if USE(LOW_BANDWIDTH_DISPLAY) -const unsigned int cMaxPendingSourceLengthInLowBandwidthDisplay = 128 * 1024; -#endif - -struct FormSubmission { - const char* action; - String url; - RefPtr<FormData> data; - String target; - String contentType; - String boundary; - RefPtr<Event> event; - - FormSubmission(const char* a, const String& u, PassRefPtr<FormData> d, const String& t, - const String& ct, const String& b, PassRefPtr<Event> e) - : action(a) - , url(u) - , data(d) - , target(t) - , contentType(ct) - , boundary(b) - , event(e) - { - } -}; - -struct ScheduledRedirection { - enum Type { redirection, locationChange, historyNavigation, locationChangeDuringLoad }; - Type type; - double delay; - String url; - String referrer; - int historySteps; - bool lockHistory; - bool wasUserGesture; - - ScheduledRedirection(double redirectDelay, const String& redirectURL, bool redirectLockHistory, bool userGesture) - : type(redirection) - , delay(redirectDelay) - , url(redirectURL) - , historySteps(0) - , lockHistory(redirectLockHistory) - , wasUserGesture(userGesture) - { - } - - ScheduledRedirection(Type locationChangeType, - const String& locationChangeURL, const String& locationChangeReferrer, - bool locationChangeLockHistory, bool locationChangeWasUserGesture) - : type(locationChangeType) - , delay(0) - , url(locationChangeURL) - , referrer(locationChangeReferrer) - , historySteps(0) - , lockHistory(locationChangeLockHistory) - , wasUserGesture(locationChangeWasUserGesture) - { - } - - explicit ScheduledRedirection(int historyNavigationSteps) - : type(historyNavigation) - , delay(0) - , historySteps(historyNavigationSteps) - , lockHistory(false) - , wasUserGesture(false) - { - } -}; - -static double storedTimeOfLastCompletedLoad; -static FrameLoader::LocalLoadPolicy localLoadPolicy = FrameLoader::AllowLocalLoadsForLocalOnly; - -static bool getString(JSValue* result, String& string) -{ - if (!result) - return false; - JSLock lock(false); - UString ustring; - if (!result->getString(ustring)) - return false; - string = ustring; - return true; -} - -bool isBackForwardLoadType(FrameLoadType type) -{ - switch (type) { - case FrameLoadTypeStandard: - case FrameLoadTypeReload: - case FrameLoadTypeReloadAllowingStaleData: - case FrameLoadTypeSame: - case FrameLoadTypeRedirectWithLockedHistory: - case FrameLoadTypeReplace: - return false; - case FrameLoadTypeBack: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - return true; - } - ASSERT_NOT_REACHED(); - return false; -} - -static int numRequests(Document* document) -{ - if (!document) - return 0; - - return document->docLoader()->requestCount(); -} - -FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) - : m_frame(frame) - , m_client(client) - , m_state(FrameStateCommittedPage) - , m_loadType(FrameLoadTypeStandard) - , m_policyLoadType(FrameLoadTypeStandard) - , m_delegateIsHandlingProvisionalLoadError(false) - , m_delegateIsDecidingNavigationPolicy(false) - , m_delegateIsHandlingUnimplementablePolicy(false) - , m_firstLayoutDone(false) - , m_quickRedirectComing(false) - , m_sentRedirectNotification(false) - , m_inStopAllLoaders(false) - , m_navigationDuringLoad(false) - , m_cachePolicy(CachePolicyVerify) - , m_isExecutingJavaScriptFormAction(false) - , m_isRunningScript(false) - , m_didCallImplicitClose(false) - , m_wasUnloadEventEmitted(false) - , m_isComplete(false) - , m_isLoadingMainResource(false) - , m_cancellingWithLoadInProgress(false) - , m_needsClear(false) - , m_receivedData(false) - , m_encodingWasChosenByUser(false) - , m_containsPlugIns(false) - , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired) - , m_checkCompletedTimer(this, &FrameLoader::checkCompletedTimerFired) - , m_checkLoadCompleteTimer(this, &FrameLoader::checkLoadCompleteTimerFired) - , m_opener(0) - , m_openedByDOM(false) - , m_creatingInitialEmptyDocument(false) - , m_isDisplayingInitialEmptyDocument(false) - , m_committedFirstRealDocumentLoad(false) - , m_didPerformFirstNavigation(false) -#ifndef NDEBUG - , m_didDispatchDidCommitLoad(false) -#endif -#if USE(LOW_BANDWIDTH_DISPLAY) - , m_useLowBandwidthDisplay(true) - , m_finishedParsingDuringLowBandwidthDisplay(false) - , m_needToSwitchOutLowBandwidthDisplay(false) -#endif -{ -} - -FrameLoader::~FrameLoader() -{ - setOpener(0); - - HashSet<Frame*>::iterator end = m_openedFrames.end(); - for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it) - (*it)->loader()->m_opener = 0; - - m_client->frameLoaderDestroyed(); -} - -void FrameLoader::init() -{ - // this somewhat odd set of steps is needed to give the frame an initial empty document - m_isDisplayingInitialEmptyDocument = false; - m_creatingInitialEmptyDocument = true; - setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(String("")), SubstituteData()).get()); - setProvisionalDocumentLoader(m_policyDocumentLoader.get()); - setState(FrameStateProvisional); - m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String())); - m_provisionalDocumentLoader->finishedLoading(); - begin(KURL(), false); - end(); - m_frame->document()->cancelParsing(); - m_creatingInitialEmptyDocument = false; - m_didCallImplicitClose = true; -} - -void FrameLoader::setDefersLoading(bool defers) -{ - if (m_documentLoader) - m_documentLoader->setDefersLoading(defers); - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->setDefersLoading(defers); - if (m_policyDocumentLoader) - m_policyDocumentLoader->setDefersLoading(defers); -} - -Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest& request, const WindowFeatures& features, bool& created) -{ - ASSERT(!features.dialog || request.frameName().isEmpty()); - - if (!request.frameName().isEmpty() && request.frameName() != "_blank") { - Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName()); - if (frame && shouldAllowNavigation(frame)) { - if (!request.resourceRequest().url().isEmpty()) - frame->loader()->loadFrameRequestWithFormAndValues(request, false, 0, 0, HashMap<String, String>()); - if (Page* page = frame->page()) - page->chrome()->focus(); - created = false; - return frame; - } - } - - // FIXME: Setting the referrer should be the caller's responsibility. - FrameLoadRequest requestWithReferrer = request; - requestWithReferrer.resourceRequest().setHTTPReferrer(m_outgoingReferrer); - addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), outgoingOrigin()); - - Page* oldPage = m_frame->page(); - if (!oldPage) - return 0; - - Page* page = oldPage->chrome()->createWindow(m_frame, requestWithReferrer, features); - if (!page) - return 0; - - Frame* frame = page->mainFrame(); - if (request.frameName() != "_blank") - frame->tree()->setName(request.frameName()); - - page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible); - page->chrome()->setStatusbarVisible(features.statusBarVisible); - page->chrome()->setScrollbarsVisible(features.scrollbarsVisible); - page->chrome()->setMenubarVisible(features.menuBarVisible); - page->chrome()->setResizable(features.resizable); - - // 'x' and 'y' specify the location of the window, while 'width' and 'height' - // specify the size of the page. We can only resize the window, so - // adjust for the difference between the window size and the page size. - - FloatRect windowRect = page->chrome()->windowRect(); - FloatSize pageSize = page->chrome()->pageRect().size(); - if (features.xSet) - windowRect.setX(features.x); - if (features.ySet) - windowRect.setY(features.y); - if (features.widthSet) - windowRect.setWidth(features.width + (windowRect.width() - pageSize.width())); - if (features.heightSet) - windowRect.setHeight(features.height + (windowRect.height() - pageSize.height())); - page->chrome()->setWindowRect(windowRect); - - page->chrome()->show(); - - created = true; - return frame; -} - -bool FrameLoader::canHandleRequest(const ResourceRequest& request) -{ - return m_client->canHandleRequest(request); -} - -void FrameLoader::changeLocation(const String& url, const String& referrer, bool lockHistory, bool userGesture) -{ - changeLocation(completeURL(url), referrer, lockHistory, userGesture); -} - - -void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool lockHistory, bool userGesture) -{ - RefPtr<Frame> protect(m_frame); - - ResourceRequestCachePolicy policy = (m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh) - ? ReloadIgnoringCacheData : UseProtocolCachePolicy; - ResourceRequest request(url, referrer, policy); -#ifdef ANDROID_USER_GESTURE - request.setUserGesture(userGesture); -#endif - - if (executeIfJavaScriptURL(request.url(), userGesture)) - return; - - urlSelected(request, "_self", 0, lockHistory, userGesture); -} - -void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* event, bool lockHistory) -{ - FrameLoadRequest copy = request; - if (copy.resourceRequest().httpReferrer().isEmpty()) - copy.resourceRequest().setHTTPReferrer(m_outgoingReferrer); - addHTTPOriginIfNeeded(copy.resourceRequest(), outgoingOrigin()); - - loadFrameRequestWithFormAndValues(copy, lockHistory, event, 0, HashMap<String, String>()); -} - -void FrameLoader::urlSelected(const ResourceRequest& request, const String& _target, Event* triggeringEvent, bool lockHistory, bool userGesture) -{ - if (executeIfJavaScriptURL(request.url(), userGesture, false)) - return; - - String target = _target; - if (target.isEmpty() && m_frame->document()) - target = m_frame->document()->baseTarget(); - - FrameLoadRequest frameRequest(request, target); -#ifdef ANDROID_USER_GESTURE - frameRequest.setWasUserGesture(userGesture); -#endif - - urlSelected(frameRequest, triggeringEvent, lockHistory); -} - -bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName) -{ -#if USE(LOW_BANDWIDTH_DISPLAY) - // don't create sub-frame during low bandwidth display - if (frame()->document()->inLowBandwidthDisplay()) { - m_needToSwitchOutLowBandwidthDisplay = true; - return false; - } -#endif - - // Support for <frame src="javascript:string"> - KURL scriptURL; - KURL url; - if (protocolIs(urlString, "javascript")) { - scriptURL = KURL(urlString); - url = blankURL(); - } else - url = completeURL(urlString); - - Frame* frame = ownerElement->contentFrame(); - if (frame) - frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, userGestureHint()); - else - frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer); - - if (!frame) - return false; - - if (!scriptURL.isEmpty()) - frame->loader()->executeIfJavaScriptURL(scriptURL); - - return true; -} - -Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer) -{ - bool allowsScrolling = true; - int marginWidth = -1; - int marginHeight = -1; - if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) { - HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement); - allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff; - marginWidth = o->getMarginWidth(); - marginHeight = o->getMarginHeight(); - } - - if (!canLoad(url, referrer)) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return 0; - } - - bool hideReferrer = shouldHideReferrer(url, referrer); - RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, - allowsScrolling, marginWidth, marginHeight); - - if (!frame) { - checkCallImplicitClose(); - return 0; - } - - frame->loader()->m_isComplete = false; - - RenderObject* renderer = ownerElement->renderer(); - FrameView* view = frame->view(); - if (renderer && renderer->isWidget() && view) - static_cast<RenderWidget*>(renderer)->setWidget(view); - - checkCallImplicitClose(); - - // In these cases, the synchronous load would have finished - // before we could connect the signals, so make sure to send the - // completed() signal for the child by hand - // FIXME: In this case the Frame will have finished loading before - // it's being added to the child list. It would be a good idea to - // create the child first, then invoke the loader separately. - if (url.isEmpty() || url == blankURL()) { - frame->loader()->completed(); - frame->loader()->checkCompleted(); - } - - return frame.get(); -} - -void FrameLoader::submitFormAgain() -{ - if (m_isRunningScript) - return; - OwnPtr<FormSubmission> form(m_deferredFormSubmission.release()); - if (form) - submitForm(form->action, form->url, form->data, form->target, - form->contentType, form->boundary, form->event.get()); -} - -void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData, - const String& target, const String& contentType, const String& boundary, Event* event) -{ - ASSERT(formData); - - if (!m_frame->page()) - return; - - KURL u = completeURL(url.isNull() ? "" : url); - // FIXME: Do we really need to special-case an empty URL? - // Would it be better to just go on with the form submisson and let the I/O fail? - if (u.isEmpty()) - return; - - if (u.protocolIs("javascript")) { - m_isExecutingJavaScriptFormAction = true; - executeIfJavaScriptURL(u, false, false); - m_isExecutingJavaScriptFormAction = false; - return; - } - - if (m_isRunningScript) { - if (m_deferredFormSubmission) - return; - m_deferredFormSubmission.set(new FormSubmission(action, url, formData, target, - contentType, boundary, event)); - return; - } - - formData->generateFiles(m_frame->page()->chrome()->client()); - - FrameLoadRequest frameRequest; -#ifdef ANDROID_USER_GESTURE - frameRequest.setWasUserGesture(userGestureHint()); -#endif - - if (!m_outgoingReferrer.isEmpty()) - frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); - - frameRequest.setFrameName(target.isEmpty() ? m_frame->document()->baseTarget() : target); - - // Handle mailto: forms - bool isMailtoForm = equalIgnoringCase(u.protocol(), "mailto"); - if (isMailtoForm && strcmp(action, "GET") != 0) { - // Append body= for POST mailto, replace the whole query string for GET one. - String body = formData->flattenToString(); - String query = u.query(); - if (!query.isEmpty()) - query.append('&'); - u.setQuery(query + body); - } - - if (strcmp(action, "GET") == 0) { - u.setQuery(formData->flattenToString()); - } else { - if (!isMailtoForm) - frameRequest.resourceRequest().setHTTPBody(formData.get()); - frameRequest.resourceRequest().setHTTPMethod("POST"); - - // construct some user headers if necessary - if (contentType.isNull() || contentType == "application/x-www-form-urlencoded") - frameRequest.resourceRequest().setHTTPContentType(contentType); - else // contentType must be "multipart/form-data" - frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary); - } - - frameRequest.resourceRequest().setURL(u); - addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); - - submitForm(frameRequest, event); -} - -void FrameLoader::stopLoading(bool sendUnload) -{ - if (m_frame->document() && m_frame->document()->tokenizer()) - m_frame->document()->tokenizer()->stopParsing(); - - if (sendUnload) { - if (m_frame->document()) { - if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) { - Node* currentFocusedNode = m_frame->document()->focusedNode(); - if (currentFocusedNode) - currentFocusedNode->aboutToUnload(); - m_frame->document()->dispatchWindowEvent(eventNames().unloadEvent, false, false); - if (m_frame->document()) - m_frame->document()->updateRendering(); - m_wasUnloadEventEmitted = true; - if (m_frame->eventHandler()->pendingFrameUnloadEventCount()) - m_frame->eventHandler()->clearPendingFrameUnloadEventCount(); - if (m_frame->eventHandler()->pendingFrameBeforeUnloadEventCount()) - m_frame->eventHandler()->clearPendingFrameBeforeUnloadEventCount(); - } - } - if (m_frame->document() && !m_frame->document()->inPageCache()) - m_frame->document()->removeAllEventListenersFromAllNodes(); - } - - m_isComplete = true; // to avoid calling completed() in finishedParsing() (David) - m_isLoadingMainResource = false; - m_didCallImplicitClose = true; // don't want that one either - m_cachePolicy = CachePolicyVerify; // Why here? - - if (m_frame->document() && m_frame->document()->parsing()) { - finishedParsing(); - m_frame->document()->setParsing(false); - } - - m_workingURL = KURL(); - - if (Document* doc = m_frame->document()) { - if (DocLoader* docLoader = doc->docLoader()) - cache()->loader()->cancelRequests(docLoader); - - doc->stopActiveDOMObjects(); - -#if ENABLE(DATABASE) - doc->stopDatabases(); -#endif - } - - // tell all subframes to stop as well - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->stopLoading(sendUnload); - - cancelRedirection(); - -#if USE(LOW_BANDWIDTH_DISPLAY) - if (m_frame->document() && m_frame->document()->inLowBandwidthDisplay()) { - // Since loading is forced to stop, reset the state without really switching. - m_needToSwitchOutLowBandwidthDisplay = false; - switchOutLowBandwidthDisplayIfReady(); - } -#endif -} - -void FrameLoader::stop() -{ - // http://bugs.webkit.org/show_bug.cgi?id=10854 - // The frame's last ref may be removed and it will be deleted by checkCompleted(). - RefPtr<Frame> protector(m_frame); - - if (m_frame->document()) { - if (m_frame->document()->tokenizer()) - m_frame->document()->tokenizer()->stopParsing(); - m_frame->document()->finishParsing(); - } else - // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but - // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to - // become true. An example is when a subframe is a pure text doc, and that subframe is the - // last one to complete. - checkCompleted(); - if (m_iconLoader) - m_iconLoader->stopLoading(); -} - -bool FrameLoader::closeURL() -{ - saveDocumentState(); - stopLoading(true); - m_frame->editor()->clearUndoRedoOperations(); - return true; -} - -void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress) -{ - m_cancellingWithLoadInProgress = cancelWithLoadInProgress; - - stopRedirectionTimer(); - - m_scheduledRedirection.clear(); -} - -KURL FrameLoader::iconURL() -{ - // If this isn't a top level frame, return nothing - if (m_frame->tree() && m_frame->tree()->parent()) - return KURL(); - - // If we have an iconURL from a Link element, return that - if (m_frame->document() && !m_frame->document()->iconURL().isEmpty()) - return KURL(m_frame->document()->iconURL()); - - // Don't return a favicon iconURL unless we're http or https - if (!m_URL.protocolIs("http") && !m_URL.protocolIs("https")) - return KURL(); - - KURL url; - url.setProtocol(m_URL.protocol()); - url.setHost(m_URL.host()); - if (int port = m_URL.port()) - url.setPort(port); - url.setPath("/favicon.ico"); - return url; -} - -bool FrameLoader::didOpenURL(const KURL& url) -{ - if (m_scheduledRedirection && m_scheduledRedirection->type == ScheduledRedirection::locationChangeDuringLoad) - // A redirect was scheduled before the document was created. - // This can happen when one frame changes another frame's location. - return false; - - cancelRedirection(); - m_frame->editor()->clearLastEditCommand(); - closeURL(); - - m_isComplete = false; - m_isLoadingMainResource = true; - m_didCallImplicitClose = false; - - m_frame->setJSStatusBarText(String()); - m_frame->setJSDefaultStatusBarText(String()); - - m_URL = url; - if ((m_URL.protocolIs("http") || m_URL.protocolIs("https")) && !m_URL.host().isEmpty() && m_URL.path().isEmpty()) - m_URL.setPath("/"); - m_workingURL = m_URL; - - started(); - - return true; -} - -void FrameLoader::didExplicitOpen() -{ - m_isComplete = false; - m_didCallImplicitClose = false; - - // Calling document.open counts as committing the first real document load. - m_committedFirstRealDocumentLoad = true; - - // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results - // from a subsequent window.document.open / window.document.write call. - // Cancelling redirection here works for all cases because document.open - // implicitly precedes document.write. - cancelRedirection(); - if (m_frame->document()->url() != blankURL()) - m_URL = m_frame->document()->url(); -} - -bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) -{ - if (!url.protocolIs("javascript")) - return false; - - String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:"))); - JSValue* result = executeScript(script, userGesture); - - String scriptResult; - if (!getString(result, scriptResult)) - return true; - - SecurityOrigin* currentSecurityOrigin = 0; - if (m_frame->document()) - currentSecurityOrigin = m_frame->document()->securityOrigin(); - - // FIXME: We should always replace the document, but doing so - // synchronously can cause crashes: - // http://bugs.webkit.org/show_bug.cgi?id=16782 - if (replaceDocument) { - begin(m_URL, true, currentSecurityOrigin); - write(scriptResult); - end(); - } - - return true; -} - -JSValue* FrameLoader::executeScript(const String& script, bool forceUserGesture) -{ - return executeScript(forceUserGesture ? String() : m_URL.string(), 1, script); -} - -JSValue* FrameLoader::executeScript(const String& url, int baseLine, const String& script) -{ - if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused()) - return noValue(); - - bool wasRunningScript = m_isRunningScript; - m_isRunningScript = true; - - JSValue* result = m_frame->script()->evaluate(url, baseLine, script); - - if (!wasRunningScript) { - m_isRunningScript = false; - submitFormAgain(); - Document::updateDocumentsRendering(); - } - - return result; -} - -void FrameLoader::cancelAndClear() -{ - cancelRedirection(); - - if (!m_isComplete) - closeURL(); - - clear(false); -} - -void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects) -{ - // FIXME: Commenting out the below line causes <http://bugs.webkit.org/show_bug.cgi?id=11212>, but putting it - // back causes a measurable performance regression which we will need to fix to restore the correct behavior - // urlsBridgeKnowsAbout.clear(); - - m_frame->editor()->clear(); - - if (!m_needsClear) - return; - m_needsClear = false; - - if (m_frame->document() && !m_frame->document()->inPageCache()) { - m_frame->document()->cancelParsing(); - if (m_frame->document()->attached()) { - m_frame->document()->willRemove(); - m_frame->document()->detach(); - - m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document()); - } - } - - // Do this after detaching the document so that the unload event works. - if (clearWindowProperties) { - m_frame->clearDOMWindow(); - m_frame->script()->clearWindowShell(); - } - - m_frame->selection()->clear(); - m_frame->eventHandler()->clear(); - if (m_frame->view()) - m_frame->view()->clear(); - - m_frame->setSelectionGranularity(CharacterGranularity); - - // Do not drop the document before the ScriptController and view are cleared - // as some destructors might still try to access the document. - m_frame->setDocument(0); - m_decoder = 0; - - m_containsPlugIns = false; - - if (clearScriptObjects) - m_frame->script()->clearScriptObjects(); - - m_redirectionTimer.stop(); - m_scheduledRedirection.clear(); - - m_checkCompletedTimer.stop(); - m_checkLoadCompleteTimer.stop(); - - m_receivedData = false; - m_isDisplayingInitialEmptyDocument = false; - - if (!m_encodingWasChosenByUser) - m_encoding = String(); -} - -void FrameLoader::receivedFirstData() -{ - begin(m_workingURL, false); - - dispatchDidCommitLoad(); - dispatchWindowObjectAvailable(); - - String ptitle = m_documentLoader->title(); - // If we have a title let the WebView know about it. - if (!ptitle.isNull()) - m_client->dispatchDidReceiveTitle(ptitle); - - m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy); - m_workingURL = KURL(); - - double delay; - String url; - if (!m_documentLoader) - return; - if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url)) - return; - - if (url.isEmpty()) - url = m_URL.string(); - else - url = m_frame->document()->completeURL(url).string(); - - scheduleHTTPRedirection(delay, url); -} - -const String& FrameLoader::responseMIMEType() const -{ - return m_responseMIMEType; -} - -void FrameLoader::setResponseMIMEType(const String& type) -{ - m_responseMIMEType = type; -} - -void FrameLoader::begin() -{ - begin(KURL()); -} - -void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin) -{ - // We need to take a reference to the security origin because |clear| - // might destroy the document that owns it. - RefPtr<SecurityOrigin> forcedSecurityOrigin = origin; - - bool resetScripting = !(m_isDisplayingInitialEmptyDocument && m_frame->document() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url)); - clear(resetScripting, resetScripting); - if (dispatch) - dispatchWindowObjectAvailable(); - - m_needsClear = true; - m_isComplete = false; - m_didCallImplicitClose = false; - m_isLoadingMainResource = true; - m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument; - - KURL ref(url); - ref.setUser(String()); - ref.setPass(String()); - ref.setRef(String()); - m_outgoingReferrer = ref.string(); - m_URL = url; - - RefPtr<Document> document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode()); - m_frame->setDocument(document); - - document->setURL(m_URL); - if (m_decoder) - document->setDecoder(m_decoder.get()); - if (forcedSecurityOrigin) - document->setSecurityOrigin(forcedSecurityOrigin.get()); - - m_frame->domWindow()->setURL(document->url()); - m_frame->domWindow()->setSecurityOrigin(document->securityOrigin()); - - updatePolicyBaseURL(); - - Settings* settings = document->settings(); - document->docLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically()); -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - document->docLoader()->setBlockNetworkImage(settings && settings->blockNetworkImage()); -#endif - - if (m_documentLoader) { - String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control"); - if (!dnsPrefetchControl.isEmpty()) - document->parseDNSPrefetchControlHeader(dnsPrefetchControl); - } - -#if FRAME_LOADS_USER_STYLESHEET - KURL userStyleSheet = settings ? settings->userStyleSheetLocation() : KURL(); - if (!userStyleSheet.isEmpty()) - m_frame->setUserStyleSheetLocation(userStyleSheet); -#endif - - restoreDocumentState(); - - document->implicitOpen(); - - if (m_frame->view()) - m_frame->view()->setContentsSize(IntSize()); - -#if USE(LOW_BANDWIDTH_DISPLAY) - // Low bandwidth display is a first pass display without external resources - // used to give an instant visual feedback. We currently only enable it for - // HTML documents in the top frame. - if (document->isHTMLDocument() && !m_frame->tree()->parent() && m_useLowBandwidthDisplay) { - m_pendingSourceInLowBandwidthDisplay = String(); - m_finishedParsingDuringLowBandwidthDisplay = false; - m_needToSwitchOutLowBandwidthDisplay = false; - document->setLowBandwidthDisplay(true); - } -#endif -} - -void FrameLoader::write(const char* str, int len, bool flush) -{ - if (len == 0 && !flush) - return; - - if (len == -1) - len = strlen(str); - - Tokenizer* tokenizer = m_frame->document()->tokenizer(); - if (tokenizer && tokenizer->wantsRawData()) { - if (len > 0) - tokenizer->writeRawData(str, len); - return; - } - - if (!m_decoder) { - Settings* settings = m_frame->settings(); - m_decoder = TextResourceDecoder::create(m_responseMIMEType, settings ? settings->defaultTextEncodingName() : String()); - if (m_encoding.isEmpty()) { - Frame* parentFrame = m_frame->tree()->parent(); - if (parentFrame && parentFrame->document()->securityOrigin()->canAccess(m_frame->document()->securityOrigin())) - m_decoder->setEncoding(parentFrame->document()->inputEncoding(), TextResourceDecoder::DefaultEncoding); - } else { - m_decoder->setEncoding(m_encoding, - m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader); - } - m_frame->document()->setDecoder(m_decoder.get()); - } - - String decoded = m_decoder->decode(str, len); - if (flush) - decoded += m_decoder->flush(); - if (decoded.isEmpty()) - return; - -#if USE(LOW_BANDWIDTH_DISPLAY) - if (m_frame->document()->inLowBandwidthDisplay()) - m_pendingSourceInLowBandwidthDisplay.append(decoded); - else // reset policy which is changed in switchOutLowBandwidthDisplayIfReady() - m_frame->document()->docLoader()->setCachePolicy(m_cachePolicy); -#endif - - if (!m_receivedData) { - m_receivedData = true; - if (m_decoder->encoding().usesVisualOrdering()) - m_frame->document()->setVisuallyOrdered(); - m_frame->document()->recalcStyle(Node::Force); - } - - if (tokenizer) { - ASSERT(!tokenizer->wantsRawData()); - tokenizer->write(decoded, true); - } -} - -void FrameLoader::write(const String& str) -{ - if (str.isNull()) - return; - - if (!m_receivedData) { - m_receivedData = true; - m_frame->document()->setParseMode(Document::Strict); - } - - if (Tokenizer* tokenizer = m_frame->document()->tokenizer()) - tokenizer->write(str, true); -} - -void FrameLoader::end() -{ - m_isLoadingMainResource = false; - endIfNotLoadingMainResource(); -} - -void FrameLoader::endIfNotLoadingMainResource() -{ - if (m_isLoadingMainResource || !m_frame->page()) - return; - - // http://bugs.webkit.org/show_bug.cgi?id=10854 - // The frame's last ref may be removed and it can be deleted by checkCompleted(), - // so we'll add a protective refcount - RefPtr<Frame> protector(m_frame); - - // make sure nothing's left in there - if (m_frame->document()) { - write(0, 0, true); - m_frame->document()->finishParsing(); -#if USE(LOW_BANDWIDTH_DISPLAY) - if (m_frame->document()->inLowBandwidthDisplay()) { - m_finishedParsingDuringLowBandwidthDisplay = true; - switchOutLowBandwidthDisplayIfReady(); - } -#endif - } else - // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but - // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to - // become true. An example is when a subframe is a pure text doc, and that subframe is the - // last one to complete. - checkCompleted(); -} - -void FrameLoader::iconLoadDecisionAvailable() -{ - if (!m_mayLoadIconLater) - return; - LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this); - startIconLoader(); - m_mayLoadIconLater = false; -} - -void FrameLoader::startIconLoader() -{ - // FIXME: We kick off the icon loader when the frame is done receiving its main resource. - // But we should instead do it when we're done parsing the head element. - if (!isLoadingMainFrame()) - return; - - if (!iconDatabase() || !iconDatabase()->isEnabled()) - return; - - KURL url(iconURL()); - String urlString(url.string()); - if (urlString.isEmpty()) - return; - - // If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load - if (loadType() != FrameLoadTypeReload) { - IconLoadDecision decision = iconDatabase()->loadDecisionForIconURL(urlString, m_documentLoader.get()); - if (decision == IconLoadNo) { - LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data()); - commitIconURLToIconDatabase(url); - - // We were told not to load this icon - that means this icon is already known by the database - // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone - // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method. - // Otherwise if the icon data *is* available, notify the delegate - if (!iconDatabase()->iconDataKnownForIconURL(urlString)) { - LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data()); - m_client->registerForIconNotification(); - iconDatabase()->iconForPageURL(m_URL.string(), IntSize(0, 0)); - iconDatabase()->iconForPageURL(originalRequestURL().string(), IntSize(0, 0)); - } else - m_client->dispatchDidReceiveIcon(); - - return; - } - - if (decision == IconLoadUnknown) { - // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database - // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal - // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the - // icon is later read in from disk - LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data()); - m_mayLoadIconLater = true; - m_client->registerForIconNotification(); - commitIconURLToIconDatabase(url); - return; - } - } - - // This is either a reload or the icon database said "yes, load the icon", so kick off the load! - if (!m_iconLoader) - m_iconLoader.set(IconLoader::create(m_frame).release()); - - m_iconLoader->startLoading(); -} - -void FrameLoader::setLocalLoadPolicy(LocalLoadPolicy policy) -{ - localLoadPolicy = policy; -} - -bool FrameLoader::restrictAccessToLocal() -{ - return localLoadPolicy != FrameLoader::AllowLocalLoadsForAll; -} - -bool FrameLoader::allowSubstituteDataAccessToLocal() -{ - return localLoadPolicy != FrameLoader::AllowLocalLoadsForLocalOnly; -} - -static HashSet<String, CaseFoldingHash>& localSchemes() -{ - static HashSet<String, CaseFoldingHash> localSchemes; - - if (localSchemes.isEmpty()) { - localSchemes.add("file"); -#if PLATFORM(MAC) - localSchemes.add("applewebdata"); -#endif -#if PLATFORM(QT) - localSchemes.add("qrc"); -#endif - } - - return localSchemes; -} - -void FrameLoader::commitIconURLToIconDatabase(const KURL& icon) -{ - ASSERT(iconDatabase()); - LOG(IconDatabase, "Committing iconURL %s to database for pageURLs %s and %s", icon.string().ascii().data(), m_URL.string().ascii().data(), originalRequestURL().string().ascii().data()); - iconDatabase()->setIconURLForPageURL(icon.string(), m_URL.string()); - iconDatabase()->setIconURLForPageURL(icon.string(), originalRequestURL().string()); -} - -void FrameLoader::restoreDocumentState() -{ - Document* doc = m_frame->document(); - if (!doc) - return; - - HistoryItem* itemToRestore = 0; - - switch (loadType()) { - case FrameLoadTypeReload: -#ifndef ANDROID_HISTORY_CLIENT - case FrameLoadTypeReloadAllowingStaleData: -#endif - case FrameLoadTypeSame: - case FrameLoadTypeReplace: - break; - case FrameLoadTypeBack: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - case FrameLoadTypeRedirectWithLockedHistory: - case FrameLoadTypeStandard: -#ifdef ANDROID_HISTORY_CLIENT - case FrameLoadTypeReloadAllowingStaleData: -#endif - itemToRestore = m_currentHistoryItem.get(); - } - - if (!itemToRestore) - return; - - doc->setStateForNewFormElements(itemToRestore->documentState()); -} - -void FrameLoader::gotoAnchor() -{ - // If our URL has no ref, then we have no place we need to jump to. - // OTOH If CSS target was set previously, we want to set it to 0, recalc - // and possibly repaint because :target pseudo class may have been - // set (see bug 11321). - if (!m_URL.hasRef() && !(m_frame->document() && m_frame->document()->getCSSTarget())) - return; - - String ref = m_URL.ref(); - if (gotoAnchor(ref)) - return; - - // Try again after decoding the ref, based on the document's encoding. - if (m_decoder) - gotoAnchor(decodeURLEscapeSequences(ref, m_decoder->encoding())); -} - -void FrameLoader::finishedParsing() -{ - if (m_creatingInitialEmptyDocument) - return; - - // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves - // because doing so will cause us to re-enter the destructor when protector goes out of scope. - // Null-checking the FrameView indicates whether or not we're in the destructor. - RefPtr<Frame> protector = m_frame->view() ? m_frame : 0; - - checkCompleted(); - - if (!m_frame->view()) - return; // We are being destroyed by something checkCompleted called. - - // Check if the scrollbars are really needed for the content. - // If not, remove them, relayout, and repaint. - m_frame->view()->restoreScrollbar(); - - m_client->dispatchDidFinishDocumentLoad(); - - gotoAnchor(); -} - -void FrameLoader::loadDone() -{ - if (m_frame->document()) - checkCompleted(); -} - -void FrameLoader::checkCompleted() -{ - // Any frame that hasn't completed yet? - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - if (!child->loader()->m_isComplete) - return; - - // Have we completed before? - if (m_isComplete) - return; - - // Are we still parsing? - if (m_frame->document() && m_frame->document()->parsing()) - return; - - // Still waiting for images/scripts? - if (m_frame->document()) - if (numRequests(m_frame->document())) - return; - -#if USE(LOW_BANDWIDTH_DISPLAY) - // as switch will be called, don't complete yet - if (m_frame->document() && m_frame->document()->inLowBandwidthDisplay() && m_needToSwitchOutLowBandwidthDisplay) - return; -#endif - - // OK, completed. - m_isComplete = true; - - RefPtr<Frame> protect(m_frame); - checkCallImplicitClose(); // if we didn't do it before - - // Do not start a redirection timer for subframes here. - // That is deferred until the parent is completed. - if (m_scheduledRedirection && !m_frame->tree()->parent()) - startRedirectionTimer(); - - completed(); - if (m_frame->page()) - checkLoadComplete(); -} - -void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*) -{ - checkCompleted(); -} - -void FrameLoader::scheduleCheckCompleted() -{ - if (!m_checkCompletedTimer.isActive()) - m_checkCompletedTimer.startOneShot(0); -} - -void FrameLoader::checkLoadCompleteTimerFired(Timer<FrameLoader>*) -{ - if (!m_frame->page()) - return; - checkLoadComplete(); -} - -void FrameLoader::scheduleCheckLoadComplete() -{ - if (!m_checkLoadCompleteTimer.isActive()) - m_checkLoadCompleteTimer.startOneShot(0); -} - -void FrameLoader::checkCallImplicitClose() -{ - if (m_didCallImplicitClose || !m_frame->document() || m_frame->document()->parsing()) - return; - - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - if (!child->loader()->m_isComplete) // still got a frame running -> too early - return; - - m_didCallImplicitClose = true; - m_wasUnloadEventEmitted = false; - if (m_frame->document()) - m_frame->document()->implicitClose(); -} - -KURL FrameLoader::baseURL() const -{ - ASSERT(m_frame->document()); - return m_frame->document()->baseURL(); -} - -String FrameLoader::baseTarget() const -{ - ASSERT(m_frame->document()); - return m_frame->document()->baseTarget(); -} - -KURL FrameLoader::completeURL(const String& url) -{ - ASSERT(m_frame->document()); - return m_frame->document()->completeURL(url); -} - -void FrameLoader::scheduleHTTPRedirection(double delay, const String& url) -{ - if (delay < 0 || delay > INT_MAX / 1000) - return; - - if (!m_frame->page()) - return; - - // We want a new history item if the refresh timeout is > 1 second. - if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay) -#ifdef ANDROID_USER_GESTURE - { - bool wasUserGesture = false; - DocumentLoader* docLoader = activeDocumentLoader(); - if (docLoader) - wasUserGesture = docLoader->request().userGesture(); - scheduleRedirection(new ScheduledRedirection(delay, url, delay <= 1, wasUserGesture)); - } -#else - scheduleRedirection(new ScheduledRedirection(delay, url, delay <= 1, false)); -#endif -} - -void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool wasUserGesture) -{ - if (!m_frame->page()) - return; - - // If the URL we're going to navigate to is the same as the current one, except for the - // fragment part, we don't need to schedule the location change. - KURL parsedURL(url); - if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) { - changeLocation(url, referrer, lockHistory, wasUserGesture); - return; - } - - // Handle a location change of a page with no document as a special case. - // This may happen when a frame changes the location of another frame. - bool duringLoad = !m_committedFirstRealDocumentLoad; - - // If a redirect was scheduled during a load, then stop the current load. - // Otherwise when the current load transitions from a provisional to a - // committed state, pending redirects may be cancelled. - if (duringLoad) { - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->stopLoading(); - stopLoading(true); - } - - ScheduledRedirection::Type type = duringLoad - ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange; - scheduleRedirection(new ScheduledRedirection(type, url, referrer, lockHistory, wasUserGesture)); -} - -void FrameLoader::scheduleRefresh(bool wasUserGesture) -{ - if (!m_frame->page()) - return; - - // Handle a location change of a page with no document as a special case. - // This may happen when a frame requests a refresh of another frame. - bool duringLoad = !m_frame->document(); - - // If a refresh was scheduled during a load, then stop the current load. - // Otherwise when the current load transitions from a provisional to a - // committed state, pending redirects may be cancelled. - if (duringLoad) - stopLoading(true); - - ScheduledRedirection::Type type = duringLoad - ? ScheduledRedirection::locationChangeDuringLoad : ScheduledRedirection::locationChange; - scheduleRedirection(new ScheduledRedirection(type, m_URL.string(), m_outgoingReferrer, true, wasUserGesture)); - m_cachePolicy = CachePolicyRefresh; -} - -bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection) -{ - switch (redirection.type) { - case ScheduledRedirection::redirection: - return false; - case ScheduledRedirection::historyNavigation: - case ScheduledRedirection::locationChange: - case ScheduledRedirection::locationChangeDuringLoad: - return true; - } - ASSERT_NOT_REACHED(); - return false; -} - -void FrameLoader::scheduleHistoryNavigation(int steps) -{ - if (!m_frame->page()) - return; - - // navigation will always be allowed in the 0 steps case, which is OK because that's supposed to force a reload. - if (!canGoBackOrForward(steps)) { - cancelRedirection(); - return; - } - - // If the steps to navigate is not zero (which needs to force a reload), and if we think the navigation is going to be a fragment load - // (when the URL we're going to navigate to is the same as the current one, except for the fragment part - but not exactly the same because that's a reload), - // then we don't need to schedule the navigation. - if (steps != 0) { - KURL destination = historyURL(steps); - // FIXME: This doesn't seem like a reliable way to tell whether or not the load will be a fragment load. - if (equalIgnoringRef(m_URL, destination) && m_URL != destination) { - goBackOrForward(steps); - return; - } - } - - scheduleRedirection(new ScheduledRedirection(steps)); -} - -void FrameLoader::goBackOrForward(int distance) -{ - if (distance == 0) - return; - - Page* page = m_frame->page(); - if (!page) - return; - BackForwardList* list = page->backForwardList(); - if (!list) - return; - - HistoryItem* item = list->itemAtIndex(distance); - if (!item) { - if (distance > 0) { - int forwardListCount = list->forwardListCount(); - if (forwardListCount > 0) - item = list->itemAtIndex(forwardListCount); - } else { - int backListCount = list->backListCount(); - if (backListCount > 0) - item = list->itemAtIndex(-backListCount); - } - } - - ASSERT(item); // we should not reach this line with an empty back/forward list - if (item) - page->goToItem(item, FrameLoadTypeIndexedBackForward); -} - -void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*) -{ - ASSERT(m_frame->page()); - - OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release()); - - switch (redirection->type) { - case ScheduledRedirection::redirection: - case ScheduledRedirection::locationChange: - case ScheduledRedirection::locationChangeDuringLoad: - changeLocation(redirection->url, redirection->referrer, - redirection->lockHistory, redirection->wasUserGesture); - return; - case ScheduledRedirection::historyNavigation: - if (redirection->historySteps == 0) { - // Special case for go(0) from a frame -> reload only the frame - urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->wasUserGesture); - return; - } - // go(i!=0) from a frame navigates into the history of the frame only, - // in both IE and NS (but not in Mozilla). We can't easily do that. - goBackOrForward(redirection->historySteps); - return; - } - - ASSERT_NOT_REACHED(); -} - -/* - In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree. - The item that was the target of the user's navigation is designated as the "targetItem". - When this method is called with doClip=YES we're able to create the whole tree except for the target's children, - which will be loaded in the future. That part of the tree will be filled out as the child loads are committed. -*/ -void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame) -{ - ASSERT(childFrame); - HistoryItem* parentItem = currentHistoryItem(); - FrameLoadType loadType = this->loadType(); - FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory; - - KURL workingURL = url; - - // If we're moving in the backforward list, we might want to replace the content - // of this child frame with whatever was there at that point. - // Reload will maintain the frame contents, LoadSame will not. - if (parentItem && parentItem->children().size() && - (isBackForwardLoadType(loadType) || loadType == FrameLoadTypeReloadAllowingStaleData)) - { - HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name()); - if (childItem) { - // Use the original URL to ensure we get all the side-effects, such as - // onLoad handlers, of any redirects that happened. An example of where - // this is needed is Radar 3213556. - workingURL = KURL(childItem->originalURLString()); - // These behaviors implied by these loadTypes should apply to the child frames - childLoadType = loadType; - - if (isBackForwardLoadType(loadType)) { - // For back/forward, remember this item so we can traverse any child items as child frames load - childFrame->loader()->setProvisionalHistoryItem(childItem); - } else { - // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item - childFrame->loader()->setCurrentHistoryItem(childItem); - } - } - } - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name()); - - if (subframeArchive) - childFrame->loader()->loadArchive(subframeArchive.release()); - else -#endif -#ifdef ANDROID_USER_GESTURE - childFrame->loader()->loadURL(workingURL, referer, String(), childLoadType, 0, 0, false); -#else - childFrame->loader()->loadURL(workingURL, referer, String(), childLoadType, 0, 0); -#endif -} - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive) -{ - RefPtr<Archive> archive = prpArchive; - - ArchiveResource* mainResource = archive->mainResource(); - ASSERT(mainResource); - if (!mainResource) - return; - - SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL()); - - ResourceRequest request(mainResource->url()); -#if PLATFORM(MAC) - request.applyWebArchiveHackForMail(); -#endif - - RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData); - documentLoader->addAllArchiveResources(archive.get()); - load(documentLoader.get()); -} -#endif - -String FrameLoader::encoding() const -{ - if (m_encodingWasChosenByUser && !m_encoding.isEmpty()) - return m_encoding; - if (m_decoder && m_decoder->encoding().isValid()) - return m_decoder->encoding().name(); - Settings* settings = m_frame->settings(); - return settings ? settings->defaultTextEncodingName() : String(); -} - -bool FrameLoader::gotoAnchor(const String& name) -{ - ASSERT(m_frame->document()); - - if (!m_frame->document()->haveStylesheetsLoaded()) { - m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); - return false; - } - - m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(false); - - Node* anchorNode = m_frame->document()->getElementById(AtomicString(name)); - if (!anchorNode && !name.isEmpty()) - anchorNode = m_frame->document()->anchors()->namedItem(name, !m_frame->document()->inCompatMode()); - -#if ENABLE(SVG) - if (m_frame->document()->isSVGDocument()) { - if (name.startsWith("xpointer(")) { - // We need to parse the xpointer reference here - } else if (name.startsWith("svgView(")) { - RefPtr<SVGSVGElement> svg = static_cast<SVGDocument*>(m_frame->document())->rootElement(); - if (!svg->currentView()->parseViewSpec(name)) - return false; - svg->setUseCurrentView(true); - } else { - if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) { - RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0; - if (viewElement.get()) { - RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get())); - svg->inheritViewAttributes(viewElement.get()); - } - } - } - // FIXME: need to decide which <svg> to focus on, and zoom to that one - // FIXME: need to actually "highlight" the viewTarget(s) - } -#endif - - m_frame->document()->setCSSTarget(anchorNode); // Setting to null will clear the current target. - - // Implement the rule that "" and "top" both mean top of page as in other browsers. - if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top"))) - return false; - - // We need to update the layout before scrolling, otherwise we could - // really mess things up if an anchor scroll comes at a bad moment. - if (m_frame->document()) { - m_frame->document()->updateRendering(); - // Only do a layout if changes have occurred that make it necessary. - if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout()) - m_frame->view()->layout(); - } - - // Scroll nested layers and frames to reveal the anchor. - // Align to the top and to the closest side (this matches other browsers). - RenderObject* renderer; - IntRect rect; - if (!anchorNode) - renderer = m_frame->document()->renderer(); // top of document - else { - renderer = anchorNode->renderer(); - rect = anchorNode->getRect(); - } - if (renderer) - renderer->enclosingLayer()->scrollRectToVisible(rect, true, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways); - - return true; -} - -bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName, - const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) -{ - if (url.isEmpty() && mimeType.isEmpty()) - return false; - -#if USE(LOW_BANDWIDTH_DISPLAY) - // don't care object during low bandwidth display - if (frame()->document()->inLowBandwidthDisplay()) { - m_needToSwitchOutLowBandwidthDisplay = true; - return false; - } -#endif - - KURL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - - bool useFallback; - if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) { - Settings* settings = m_frame->settings(); - if (!settings || !settings->arePluginsEnabled() || - (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) - return false; - return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback); - } - - ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag)); - HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node()); - - // FIXME: OK to always make a new frame? When does the old frame get removed? - return loadSubframe(element, completedURL, frameName, m_outgoingReferrer); -} - -bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) -{ - // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that - // can handle TIFF (which QuickTime can also handle) they probably intended to override QT. - if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) { - String pluginName = m_frame->page()->pluginData()->pluginNameForMimeType(mimeType); - if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) - return true; - } - - ObjectContentType objectType = m_client->objectContentType(url, mimeType); - // If an object's content can't be handled and it has no fallback, let - // it be handled as a plugin to show the broken plugin icon. - useFallback = objectType == ObjectContentNone && hasFallback; - return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin; -} - -bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) -{ - Widget* widget = 0; - - if (renderer && !useFallback) { - Element* pluginElement = 0; - if (renderer->node() && renderer->node()->isElementNode()) - pluginElement = static_cast<Element*>(renderer->node()); - - if (!canLoad(url, String(), frame()->document())) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return false; - } - - widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), - pluginElement, url, paramNames, paramValues, mimeType, - m_frame->document()->isPluginDocument()); - if (widget) { - renderer->setWidget(widget); - m_containsPlugIns = true; - } - } - - return widget != 0; -} - -void FrameLoader::clearRecordedFormValues() -{ - m_formAboutToBeSubmitted = 0; - m_formValuesAboutToBeSubmitted.clear(); -} - -void FrameLoader::setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element) -{ - m_formAboutToBeSubmitted = element; -} - -void FrameLoader::recordFormValue(const String& name, const String& value) -{ - m_formValuesAboutToBeSubmitted.set(name, value); -} - -void FrameLoader::parentCompleted() -{ - if (m_scheduledRedirection && !m_redirectionTimer.isActive()) - startRedirectionTimer(); -} - -String FrameLoader::outgoingReferrer() const -{ - return m_outgoingReferrer; -} - -String FrameLoader::outgoingOrigin() const -{ - if (m_frame->document()) - return m_frame->document()->securityOrigin()->toString(); - - return SecurityOrigin::createEmpty()->toString(); -} - -Frame* FrameLoader::opener() -{ - return m_opener; -} - -void FrameLoader::setOpener(Frame* opener) -{ - if (m_opener) - m_opener->loader()->m_openedFrames.remove(m_frame); - if (opener) - opener->loader()->m_openedFrames.add(m_frame); - m_opener = opener; - - if (m_frame->document()) { - m_frame->document()->initSecurityContext(); - m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin()); - } -} - -bool FrameLoader::openedByDOM() const -{ - return m_openedByDOM; -} - -void FrameLoader::setOpenedByDOM() -{ - m_openedByDOM = true; -} - -void FrameLoader::handleFallbackContent() -{ - HTMLFrameOwnerElement* owner = m_frame->ownerElement(); - if (!owner || !owner->hasTagName(objectTag)) - return; - static_cast<HTMLObjectElement*>(owner)->renderFallbackContent(); -} - -void FrameLoader::provisionalLoadStarted() -{ -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree()->parent()) - android::TimeCounter::reset(); -#endif - - Page* page = m_frame->page(); - - // this is used to update the current history item - // in the event of a navigation aytime during loading - m_navigationDuringLoad = false; - if (page) { - Document *document = page->mainFrame()->document(); - m_navigationDuringLoad = !page->mainFrame()->loader()->isComplete() || (document && document->processingLoadEvent()); - } - - m_firstLayoutDone = false; - cancelRedirection(true); - m_client->provisionalLoadStarted(); -} - -bool FrameLoader::userGestureHint() -{ - Frame* rootFrame = m_frame; - while (rootFrame->tree()->parent()) - rootFrame = rootFrame->tree()->parent(); - - if (rootFrame->script()->isEnabled()) - return rootFrame->script()->processingUserGesture(); - - return true; // If JavaScript is disabled, a user gesture must have initiated the navigation -} - -void FrameLoader::didNotOpenURL(const KURL& url) -{ - if (m_submittedFormURL == url) - m_submittedFormURL = KURL(); -} - -void FrameLoader::resetMultipleFormSubmissionProtection() -{ - m_submittedFormURL = KURL(); -} - -void FrameLoader::setEncoding(const String& name, bool userChosen) -{ - if (!m_workingURL.isEmpty()) - receivedFirstData(); - m_encoding = name; - m_encodingWasChosenByUser = userChosen; -} - -void FrameLoader::addData(const char* bytes, int length) -{ - ASSERT(m_workingURL.isEmpty()); - ASSERT(m_frame->document()); - ASSERT(m_frame->document()->parsing()); - write(bytes, length); -} - -bool FrameLoader::canCachePage() -{ - // Cache the page, if possible. - // Don't write to the cache if in the middle of a redirect, since we will want to - // store the final page we end up on. - // No point writing to the cache on a reload or loadSame, since we will just write - // over it again when we leave that page. - // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they - // are the most interesting pages on the web, and often those that would benefit the most from caching! - FrameLoadType loadType = this->loadType(); - - return m_documentLoader - && m_documentLoader->mainDocumentError().isNull() - && !m_frame->tree()->childCount() - && !m_frame->tree()->parent() - // FIXME: If we ever change this so that pages with plug-ins will be cached, - // we need to make sure that we don't cache pages that have outstanding NPObjects - // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in, - // they would need to be destroyed and then recreated, and there is no way that we can recreate - // the right NPObjects. See <rdar://problem/5197041> for more information. - && !m_containsPlugIns - && !m_URL.protocolIs("https") - && m_frame->document() - && !m_frame->document()->hasWindowEventListener(eventNames().unloadEvent) -#if ENABLE(DATABASE) - && !m_frame->document()->hasOpenDatabases() -#endif - && !m_frame->document()->usingGeolocation() - && m_frame->page() - && m_frame->page()->backForwardList()->enabled() - && m_frame->page()->backForwardList()->capacity() > 0 - && m_frame->page()->settings()->usesPageCache() - && m_currentHistoryItem - && !isQuickRedirectComing() - && loadType != FrameLoadTypeReload - && loadType != FrameLoadTypeReloadAllowingStaleData - && loadType != FrameLoadTypeSame - && !m_documentLoader->isLoadingInAPISense() - && !m_documentLoader->isStopping() -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - // FIXME: We should investigating caching pages that have an associated - // application cache. <rdar://problem/5917899> tracks that work. - && !m_documentLoader->applicationCache() - && !m_documentLoader->candidateApplicationCacheGroup() -#endif - ; -} - -void FrameLoader::updatePolicyBaseURL() -{ - if (m_frame->tree()->parent() && m_frame->tree()->parent()->document()) - setPolicyBaseURL(m_frame->tree()->parent()->document()->policyBaseURL()); - else - setPolicyBaseURL(m_URL); -} - -void FrameLoader::setPolicyBaseURL(const KURL& url) -{ - if (m_frame->document()) - m_frame->document()->setPolicyBaseURL(url); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->setPolicyBaseURL(url); -} - -// This does the same kind of work that didOpenURL does, except it relies on the fact -// that a higher level already checked that the URLs match and the scrolling is the right thing to do. -void FrameLoader::scrollToAnchor(const KURL& url) -{ - m_URL = url; - updateHistoryForAnchorScroll(); - - // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor - m_frame->eventHandler()->stopAutoscrollTimer(); - started(); - gotoAnchor(); - - // It's important to model this as a load that starts and immediately finishes. - // Otherwise, the parent frame may think we never finished loading. - m_isComplete = false; - checkCompleted(); -} - -bool FrameLoader::isComplete() const -{ - return m_isComplete; -} - -void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection) -{ - ASSERT(m_frame->page()); - - stopRedirectionTimer(); - m_scheduledRedirection.set(redirection); - if (!m_isComplete && redirection->type != ScheduledRedirection::redirection) - completed(); - if (m_isComplete || redirection->type != ScheduledRedirection::redirection) - startRedirectionTimer(); -} - -void FrameLoader::startRedirectionTimer() -{ - ASSERT(m_frame->page()); - ASSERT(m_scheduledRedirection); - - m_redirectionTimer.stop(); - m_redirectionTimer.startOneShot(m_scheduledRedirection->delay); - - switch (m_scheduledRedirection->type) { - case ScheduledRedirection::redirection: - case ScheduledRedirection::locationChange: - case ScheduledRedirection::locationChangeDuringLoad: - clientRedirected(KURL(m_scheduledRedirection->url), - m_scheduledRedirection->delay, - currentTime() + m_redirectionTimer.nextFireInterval(), - m_scheduledRedirection->lockHistory, - m_isExecutingJavaScriptFormAction); - return; - case ScheduledRedirection::historyNavigation: - // Don't report history navigations. - return; - } - ASSERT_NOT_REACHED(); -} - -void FrameLoader::stopRedirectionTimer() -{ - if (!m_redirectionTimer.isActive()) - return; - - m_redirectionTimer.stop(); - - if (m_scheduledRedirection) { - switch (m_scheduledRedirection->type) { - case ScheduledRedirection::redirection: - case ScheduledRedirection::locationChange: - case ScheduledRedirection::locationChangeDuringLoad: - clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress); - return; - case ScheduledRedirection::historyNavigation: - // Don't report history navigations. - return; - } - ASSERT_NOT_REACHED(); - } -} - -void FrameLoader::completed() -{ - RefPtr<Frame> protect(m_frame); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->parentCompleted(); - if (Frame* parent = m_frame->tree()->parent()) - parent->loader()->checkCompleted(); - submitFormAgain(); -} - -void FrameLoader::started() -{ - for (Frame* frame = m_frame; frame; frame = frame->tree()->parent()) - frame->loader()->m_isComplete = false; -} - -bool FrameLoader::containsPlugins() const -{ - return m_containsPlugIns; -} - -void FrameLoader::prepareForLoadStart() -{ - if (Page* page = m_frame->page()) - page->progress()->progressStarted(m_frame); - m_client->dispatchDidStartProvisionalLoad(); -} - -void FrameLoader::setupForReplace() -{ - setState(FrameStateProvisional); - m_provisionalDocumentLoader = m_documentLoader; - m_documentLoader = 0; - detachChildren(); -} - -void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType) -{ - activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType); -} - -void FrameLoader::loadFrameRequestWithFormState(const FrameLoadRequest& request, bool lockHistory, Event* event, PassRefPtr<FormState> prpFormState) -{ - RefPtr<FormState> formState = prpFormState; - KURL url = request.resourceRequest().url(); - - String referrer; - String argsReferrer = request.resourceRequest().httpReferrer(); - if (!argsReferrer.isEmpty()) - referrer = argsReferrer; - else - referrer = m_outgoingReferrer; - - ASSERT(frame()->document()); - if (url.protocolIs("file")) { - if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return; - } - } - - if (shouldHideReferrer(url, referrer)) - referrer = String(); - - Frame* targetFrame = findFrameForNavigation(request.frameName()); - - if (request.resourceRequest().httpMethod() != "POST") { - FrameLoadType loadType; - if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData) - loadType = FrameLoadTypeReload; - else if (lockHistory) - loadType = FrameLoadTypeRedirectWithLockedHistory; - else - loadType = FrameLoadTypeStandard; - -#ifdef ANDROID_USER_GESTURE - loadURL(request.resourceRequest().url(), referrer, request.frameName(), loadType, - event, formState.release(), request.wasUserGesture()); -#else - loadURL(request.resourceRequest().url(), referrer, request.frameName(), loadType, - event, formState.release()); -#endif - } else -#ifdef ANDROID_USER_GESTURE - loadPostRequest(request.resourceRequest(), referrer, request.frameName(), event, formState.release(), request.wasUserGesture()); -#else - loadPostRequest(request.resourceRequest(), referrer, request.frameName(), event, formState.release()); -#endif - - if (targetFrame && targetFrame != m_frame) - if (Page* page = targetFrame->page()) - page->chrome()->focus(); -} - -void FrameLoader::loadFrameRequestWithFormAndValues(const FrameLoadRequest& request, bool lockHistory, Event* event, - HTMLFormElement* submitForm, const HashMap<String, String>& formValues) -{ - RefPtr<FormState> formState; - if (submitForm) - formState = FormState::create(submitForm, formValues, m_frame); - - loadFrameRequestWithFormState(request, lockHistory, event, formState.release()); -} - -#ifdef ANDROID_USER_GESTURE -void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, FrameLoadType newLoadType, - Event* event, PassRefPtr<FormState> prpFormState, bool userGesture) -#else -void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, FrameLoadType newLoadType, - Event* event, PassRefPtr<FormState> prpFormState) -#endif -{ - RefPtr<FormState> formState = prpFormState; - bool isFormSubmission = formState; - - ResourceRequest request(newURL); -#ifdef ANDROID_USER_GESTURE - request.setUserGesture(userGesture); -#endif - if (!referrer.isEmpty()) { - request.setHTTPReferrer(referrer); - RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer); - addHTTPOriginIfNeeded(request, referrerOrigin->toString()); - } - addExtraFieldsToRequest(request, true, event || isFormSubmission); - if (newLoadType == FrameLoadTypeReload) - request.setCachePolicy(ReloadIgnoringCacheData); - - ASSERT(newLoadType != FrameLoadTypeSame); - - NavigationAction action(newURL, newLoadType, isFormSubmission, event); - - if (!frameName.isEmpty()) { - if (Frame* targetFrame = findFrameForNavigation(frameName)) -#ifdef ANDROID_USER_GESTURE - targetFrame->loader()->loadURL(newURL, referrer, String(), newLoadType, event, formState, userGesture); -#else - targetFrame->loader()->loadURL(newURL, referrer, String(), newLoadType, event, formState); -#endif - else - checkNewWindowPolicy(action, request, formState, frameName); - return; - } - - RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader; - - bool sameURL = shouldTreatURLAsSameAsCurrent(newURL); - - // Make sure to do scroll to anchor processing even if the URL is - // exactly the same so pages with '#' links and DHTML side effects - // work properly. - if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) { - oldDocumentLoader->setTriggeringAction(action); - stopPolicyCheck(); - checkNavigationPolicy(request, oldDocumentLoader.get(), formState, - callContinueFragmentScrollAfterNavigationPolicy, this); - } else { - // must grab this now, since this load may stop the previous load and clear this flag - bool isRedirect = m_quickRedirectComing; - loadWithNavigationAction(request, action, newLoadType, formState); - if (isRedirect) { - m_quickRedirectComing = false; - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->setIsClientRedirect(true); -#ifdef ANDROID_HISTORY_CLIENT - } else if (sameURL && (newLoadType != FrameLoadTypeReloadAllowingStaleData)) -#else - } else if (sameURL) -#endif - // Example of this case are sites that reload the same URL with a different cookie - // driving the generated content, or a master frame with links that drive a target - // frame, where the user has clicked on the same link repeatedly. - m_loadType = FrameLoadTypeSame; - } -} - -void FrameLoader::load(const ResourceRequest& request) -{ - load(request, SubstituteData()); -} - -void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData) -{ - if (m_inStopAllLoaders) - return; - - // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted. - m_loadType = FrameLoadTypeStandard; - load(m_client->createDocumentLoader(request, substituteData).get()); -} - -void FrameLoader::load(const ResourceRequest& request, const String& frameName) -{ - if (frameName.isEmpty()) { - load(request); - return; - } - - Frame* frame = findFrameForNavigation(frameName); - if (frame) { - frame->loader()->load(request); - return; - } - - checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName); -} - -void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState) -{ - RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData()); - - loader->setTriggeringAction(action); - if (m_documentLoader) - loader->setOverrideEncoding(m_documentLoader->overrideEncoding()); - - loadWithDocumentLoader(loader.get(), type, formState); -} - -void FrameLoader::load(DocumentLoader* newDocumentLoader) -{ - ResourceRequest& r = newDocumentLoader->request(); - addExtraFieldsToRequest(r, true, false); - FrameLoadType type; - - if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) { - r.setCachePolicy(ReloadIgnoringCacheData); - type = FrameLoadTypeSame; - } else - type = FrameLoadTypeStandard; - - if (m_documentLoader) - newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding()); - - // When we loading alternate content for an unreachable URL that we're - // visiting in the history list, we treat it as a reload so the history list - // is appropriately maintained. - // - // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ... - // shouldn't a more explicit type of reload be defined, that means roughly - // "load without affecting history" ? - if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) { - ASSERT(type == FrameLoadTypeStandard); - type = FrameLoadTypeReload; - } - - loadWithDocumentLoader(newDocumentLoader, type, 0); -} - -void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState) -{ - ASSERT(m_client->hasWebView()); - - // Unfortunately the view must be non-nil, this is ultimately due - // to parser requiring a FrameView. We should fix this dependency. - - ASSERT(m_frame->view()); - - m_policyLoadType = type; - RefPtr<FormState> formState = prpFormState; - bool isFormSubmission = formState; - - const KURL& newURL = loader->request().url(); - - if (shouldScrollToAnchor(isFormSubmission, m_policyLoadType, newURL)) { - RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader; - NavigationAction action(newURL, m_policyLoadType, isFormSubmission); - - oldDocumentLoader->setTriggeringAction(action); - stopPolicyCheck(); - checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState, - callContinueFragmentScrollAfterNavigationPolicy, this); - } else { - if (Frame* parent = m_frame->tree()->parent()) - loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding()); - - stopPolicyCheck(); - setPolicyDocumentLoader(loader); - - checkNavigationPolicy(loader->request(), loader, formState, - callContinueLoadAfterNavigationPolicy, this); - } -} - -bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Document* doc) -{ - // We can always load any URL that isn't considered local (e.g. http URLs) - if (!shouldTreatURLAsLocal(url.string())) - return true; - - // If we were provided a document, we let its local file policy dictate the result, - // otherwise we allow local loads only if the supplied referrer is also local. - if (doc) - return doc->securityOrigin()->canLoadLocalResources(); - else if (!referrer.isEmpty()) - return shouldTreatURLAsLocal(referrer); - else - return false; -} - -void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url) -{ - ASSERT(!url.isEmpty()); - if (!frame) - return; - - frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String()); -} - -bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer) -{ - bool referrerIsSecureURL = protocolIs(referrer, "https"); - bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http"); - - if (!referrerIsWebURL) - return true; - - if (!referrerIsSecureURL) - return false; - - bool URLIsSecureURL = url.protocolIs("https"); - - return !URLIsSecureURL; -} - -const ResourceRequest& FrameLoader::initialRequest() const -{ - return activeDocumentLoader()->originalRequest(); -} - -void FrameLoader::receivedData(const char* data, int length) -{ - activeDocumentLoader()->receivedData(data, length); -} - -void FrameLoader::handleUnimplementablePolicy(const ResourceError& error) -{ - m_delegateIsHandlingUnimplementablePolicy = true; - m_client->dispatchUnableToImplementPolicy(error); - m_delegateIsHandlingUnimplementablePolicy = false; -} - -void FrameLoader::cannotShowMIMEType(const ResourceResponse& response) -{ - handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response)); -} - -ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request) -{ - return m_client->interruptForPolicyChangeError(request); -} - -void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument) -{ - checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument); -} - -void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument) -{ - ASSERT(activeDocumentLoader()); - - // Always show content with valid substitute data. - if (activeDocumentLoader()->substituteData().isValid()) { - function(argument, PolicyUse); - return; - } - -#if ENABLE(FTPDIR) - // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it - Settings* settings = m_frame->settings(); - if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") { - function(argument, PolicyUse); - return; - } -#endif - - m_policyCheck.set(function, argument); - m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy, - MIMEType, activeDocumentLoader()->request()); -} - -bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader) -{ - KURL unreachableURL = docLoader->unreachableURL(); - - if (unreachableURL.isEmpty()) - return false; - - if (!isBackForwardLoadType(m_policyLoadType)) - return false; - - // We only treat unreachableURLs specially during the delegate callbacks - // for provisional load errors and navigation policy decisions. The former - // case handles well-formed URLs that can't be loaded, and the latter - // case handles malformed URLs and unknown schemes. Loading alternate content - // at other times behaves like a standard load. - DocumentLoader* compareDocumentLoader = 0; - if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy) - compareDocumentLoader = m_policyDocumentLoader.get(); - else if (m_delegateIsHandlingProvisionalLoadError) - compareDocumentLoader = m_provisionalDocumentLoader.get(); - - return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url(); -} - -void FrameLoader::reloadAllowingStaleData(const String& encoding) -{ - if (!m_documentLoader) - return; - - ResourceRequest request = m_documentLoader->request(); - KURL unreachableURL = m_documentLoader->unreachableURL(); - if (!unreachableURL.isEmpty()) - request.setURL(unreachableURL); - - request.setCachePolicy(ReturnCacheDataElseLoad); - - RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData()); - setPolicyDocumentLoader(loader.get()); - - loader->setOverrideEncoding(encoding); - - loadWithDocumentLoader(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0); -} - -void FrameLoader::reload() -{ - if (!m_documentLoader) - return; - - ResourceRequest& initialRequest = m_documentLoader->request(); - - // If a window is created by javascript, its main frame can have an empty but non-nil URL. - // Reloading in this case will lose the current contents (see 4151001). - if (initialRequest.url().isEmpty()) - return; - - // Replace error-page URL with the URL we were trying to reach. - KURL unreachableURL = m_documentLoader->unreachableURL(); - if (!unreachableURL.isEmpty()) - initialRequest = ResourceRequest(unreachableURL); - - // Create a new document loader for the reload, this will become m_documentLoader eventually, - // but first it has to be the "policy" document loader, and then the "provisional" document loader. - RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData()); - - ResourceRequest& request = loader->request(); - - request.setCachePolicy(ReloadIgnoringCacheData); - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - - // If we're about to re-post, set up action so the application can warn the user. - if (request.httpMethod() == "POST") - loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted)); - - loader->setOverrideEncoding(m_documentLoader->overrideEncoding()); - - loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0); -} - -static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame) -{ - // targetFrame can be NULL when we're trying to navigate a top-level frame - // that has a NULL opener. - if (!targetFrame) - return false; - - for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) { - Document* ancestorDocument = ancestorFrame->document(); - if (!ancestorDocument) - return true; - - const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin(); - if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin)) - return true; - } - - return false; -} - -bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const -{ - // The navigation change is safe if the active frame is: - // - in the same security origin as the target or one of the target's - // ancestors. - // - // Or the target frame is: - // - a top-level frame in the frame hierarchy and the active frame can - // navigate the target frame's opener per above. - - if (!targetFrame) - return true; - - // Performance optimization. - if (m_frame == targetFrame) - return true; - - // Let a frame navigate the top-level window that contains it. This is - // important to allow because it lets a site "frame-bust" (escape from a - // frame created by another web site). - if (targetFrame == m_frame->tree()->top()) - return true; - - Document* activeDocument = m_frame->document(); - ASSERT(activeDocument); - const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin(); - - // For top-level windows, check the opener. - if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener())) - return true; - - // In general, check the frame's ancestors. - if (canAccessAncestor(activeSecurityOrigin, targetFrame)) - return true; - - Settings* settings = targetFrame->settings(); - if (settings && !settings->privateBrowsingEnabled()) { - Document* targetDocument = targetFrame->document(); - // FIXME: this error message should contain more specifics of why the navigation change is not allowed. - String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n", - targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data()); - - // FIXME: should we print to the console of the activeFrame as well? - targetFrame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String()); - } - - return false; -} - -void FrameLoader::stopLoadingSubframes() -{ - for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->stopAllLoaders(); -} - -void FrameLoader::stopAllLoaders() -{ - // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. - if (m_inStopAllLoaders) - return; - - m_inStopAllLoaders = true; - - stopPolicyCheck(); - - stopLoadingSubframes(); - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->stopLoading(); - if (m_documentLoader) - m_documentLoader->stopLoading(); - - setProvisionalDocumentLoader(0); - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (m_documentLoader) - m_documentLoader->clearArchiveResources(); -#endif - - m_inStopAllLoaders = false; -} - -void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete) -{ - stopAllLoaders(); - - if (deferCheckLoadComplete) - scheduleCheckLoadComplete(); - else if (m_frame->page()) - checkLoadComplete(); -} - -DocumentLoader* FrameLoader::activeDocumentLoader() const -{ - if (m_state == FrameStateProvisional) - return m_provisionalDocumentLoader.get(); - return m_documentLoader.get(); -} - -bool FrameLoader::isLoading() const -{ - DocumentLoader* docLoader = activeDocumentLoader(); - if (!docLoader) - return false; - return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns(); -} - -bool FrameLoader::frameHasLoaded() const -{ - return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument); -} - -void FrameLoader::setDocumentLoader(DocumentLoader* loader) -{ - if (!loader && !m_documentLoader) - return; - - ASSERT(loader != m_documentLoader); - ASSERT(!loader || loader->frameLoader() == this); - - m_client->prepareForDataSourceReplacement(); - detachChildren(); - if (m_documentLoader) - m_documentLoader->detachFromFrame(); - - m_documentLoader = loader; -} - -DocumentLoader* FrameLoader::documentLoader() const -{ - return m_documentLoader.get(); -} - -void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader) -{ - if (m_policyDocumentLoader == loader) - return; - - ASSERT(m_frame); - if (loader) - loader->setFrame(m_frame); - if (m_policyDocumentLoader - && m_policyDocumentLoader != m_provisionalDocumentLoader - && m_policyDocumentLoader != m_documentLoader) - m_policyDocumentLoader->detachFromFrame(); - - m_policyDocumentLoader = loader; -} - -DocumentLoader* FrameLoader::policyDocumentLoader() const -{ - return m_policyDocumentLoader.get(); -} - -DocumentLoader* FrameLoader::provisionalDocumentLoader() const -{ - return m_provisionalDocumentLoader.get(); -} - -void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader) -{ - ASSERT(!loader || !m_provisionalDocumentLoader); - ASSERT(!loader || loader->frameLoader() == this); - - if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader) - m_provisionalDocumentLoader->detachFromFrame(); - - m_provisionalDocumentLoader = loader; -} - -FrameState FrameLoader::state() const -{ - return m_state; -} - -double FrameLoader::timeOfLastCompletedLoad() -{ - return storedTimeOfLastCompletedLoad; -} - -void FrameLoader::setState(FrameState newState) -{ - m_state = newState; - - if (newState == FrameStateProvisional) - provisionalLoadStarted(); - else if (newState == FrameStateComplete) { - frameLoadCompleted(); - storedTimeOfLastCompletedLoad = currentTime(); - if (m_documentLoader) - m_documentLoader->stopRecordingResponses(); - } -} - -void FrameLoader::clearProvisionalLoad() -{ - setProvisionalDocumentLoader(0); - if (Page* page = m_frame->page()) - page->progress()->progressCompleted(m_frame); - setState(FrameStateComplete); -} - -void FrameLoader::markLoadComplete() -{ - setState(FrameStateComplete); -} - -void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage) -{ - RefPtr<CachedPage> cachedPage = prpCachedPage; - RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader; - - // Check to see if we need to cache the page we are navigating away from into the back/forward cache. - // We are doing this here because we know for sure that a new page is about to be loaded. - if (canCachePage() && m_client->canCachePage() && !m_currentHistoryItem->isInPageCache()) - cachePageForHistoryItem(m_currentHistoryItem.get()); - else if (m_frame->page() && m_frame == m_frame->page()->mainFrame()) { - // If the main frame installs a timeout late enough (for example in its onunload handler) - // it could sometimes fire when transitioning to a non-HTML document representation (such as the Mac bookmarks view). - // To avoid this, we clear all timeouts if the page is not to be cached in the back forward list. - // Cached pages have their timers paused so they are fine. - ScriptController* proxy = m_frame->script(); - if (proxy->haveWindowShell()) - proxy->windowShell()->window()->clearAllTimeouts(); - } - - if (m_loadType != FrameLoadTypeReplace) - closeOldDataSources(); - - if (!cachedPage && !m_creatingInitialEmptyDocument) - m_client->makeRepresentation(pdl.get()); - - transitionToCommitted(cachedPage); - - // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's - // status has changed, if there was a redirect. The frame load delegate may have saved some state about - // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are - // just about to commit a new page, there cannot possibly be a pending redirect at this point. - if (m_sentRedirectNotification) - clientRedirectCancelledOrFinished(false); - - if (cachedPage && cachedPage->document()) { - open(*cachedPage); - cachedPage->clear(); - } else { - KURL url = pdl->substituteData().responseURL(); - if (url.isEmpty()) - url = pdl->url(); - if (url.isEmpty()) - url = pdl->responseURL(); - if (url.isEmpty()) - url = blankURL(); - - didOpenURL(url); - } - opened(); -} - -void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) -{ - ASSERT(m_client->hasWebView()); - ASSERT(m_state == FrameStateProvisional); - - if (m_state != FrameStateProvisional) - return; - - m_client->setCopiesOnScroll(); - updateHistoryForCommit(); - - // The call to closeURL() invokes the unload event handler, which can execute arbitrary - // JavaScript. If the script initiates a new load, we need to abandon the current load, - // or the two will stomp each other. - DocumentLoader* pdl = m_provisionalDocumentLoader.get(); - if (m_documentLoader) - closeURL(); - if (pdl != m_provisionalDocumentLoader) - return; - - // Nothing else can interupt this commit - set the Provisional->Committed transition in stone - if (m_documentLoader) - m_documentLoader->stopLoadingSubresources(); - if (m_documentLoader) - m_documentLoader->stopLoadingPlugIns(); - - setDocumentLoader(m_provisionalDocumentLoader.get()); - setProvisionalDocumentLoader(0); - setState(FrameStateCommittedPage); - - // Handle adding the URL to the back/forward list. - DocumentLoader* dl = m_documentLoader.get(); - String ptitle = dl->title(); - - switch (m_loadType) { - case FrameLoadTypeForward: - case FrameLoadTypeBack: - case FrameLoadTypeIndexedBackForward: - if (Page* page = m_frame->page()) - if (page->backForwardList()) { - updateHistoryForBackForwardNavigation(); - - // Create a document view for this document, or used the cached view. - if (cachedPage) { - DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader(); - ASSERT(cachedDocumentLoader); - cachedDocumentLoader->setFrame(m_frame); - m_client->transitionToCommittedFromCachedPage(cachedPage.get()); - - } else - m_client->transitionToCommittedForNewPage(); - } - break; - - case FrameLoadTypeReload: - case FrameLoadTypeSame: - case FrameLoadTypeReplace: - updateHistoryForReload(); - m_client->transitionToCommittedForNewPage(); - break; - - // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case - case FrameLoadTypeReloadAllowingStaleData: - m_client->transitionToCommittedForNewPage(); - break; - - case FrameLoadTypeStandard: - updateHistoryForStandardLoad(); -#ifndef BUILDING_ON_TIGER - // This code was originally added for a Leopard performance imporvement. We decided to - // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>. - if (m_frame->view()) - m_frame->view()->setScrollbarsSuppressed(true); -#endif - m_client->transitionToCommittedForNewPage(); - break; - - case FrameLoadTypeRedirectWithLockedHistory: - updateHistoryForRedirectWithLockedHistory(); - m_client->transitionToCommittedForNewPage(); - break; - - // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is). - // An exception should be thrown if we're in the FrameLoadTypeUninitialized state. - default: - ASSERT_NOT_REACHED(); - } - - m_responseMIMEType = dl->responseMIMEType(); - - // Tell the client we've committed this URL. - ASSERT(m_frame->view()); - - if (m_creatingInitialEmptyDocument) - return; - - m_committedFirstRealDocumentLoad = true; - - // For non-cached HTML pages, these methods are called in FrameLoader::begin. - if (cachedPage || !m_client->hasHTMLView()) { - dispatchDidCommitLoad(); - - // If we have a title let the WebView know about it. - if (!ptitle.isNull()) - m_client->dispatchDidReceiveTitle(ptitle); - } -} - -void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress) -{ - // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if - // the redirect succeeded. We should either rename this API, or add a new method, like - // -webView:didFinishClientRedirectForFrame: - m_client->dispatchDidCancelClientRedirect(); - - if (!cancelWithLoadInProgress) - m_quickRedirectComing = false; - - m_sentRedirectNotification = false; -} - -void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockHistory, bool isJavaScriptFormAction) -{ - m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate); - - // Remember that we sent a redirect notification to the frame load delegate so that when we commit - // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame: - m_sentRedirectNotification = true; - - // If a "quick" redirect comes in an, we set a special mode so we treat the next - // load as part of the same navigation. If we don't have a document loader, we have - // no "original" load on which to base a redirect, so we treat the redirect as a normal load. - m_quickRedirectComing = lockHistory && m_documentLoader && !isJavaScriptFormAction; -} - -bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL) -{ - // This function implements the rule: "Don't reload if navigating by fragment within - // the same URL, but do reload if going to a new URL or to the same URL with no - // fragment identifier at all." - if (!destinationURL.hasRef()) - return true; - return !equalIgnoringRef(currentURL, destinationURL); -} - -void FrameLoader::closeOldDataSources() -{ - // FIXME: Is it important for this traversal to be postorder instead of preorder? - // If so, add helpers for postorder traversal, and use them. If not, then lets not - // use a recursive algorithm here. - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->closeOldDataSources(); - - if (m_documentLoader) - m_client->dispatchWillClose(); - - m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers -} - -void FrameLoader::open(CachedPage& cachedPage) -{ - ASSERT(m_frame->page()); - ASSERT(m_frame->page()->mainFrame() == m_frame); - - cancelRedirection(); - - // We still have to close the previous part page. - closeURL(); - - m_isComplete = false; - - // Don't re-emit the load event. - m_didCallImplicitClose = true; - - // Delete old status bar messages (if it _was_ activated on last URL). - if (m_frame->script()->isEnabled()) { - m_frame->setJSStatusBarText(String()); - m_frame->setJSDefaultStatusBarText(String()); - } - - KURL url = cachedPage.url(); - - if ((url.protocolIs("http") || url.protocolIs("https")) && !url.host().isEmpty() && url.path().isEmpty()) - url.setPath("/"); - - m_URL = url; - m_workingURL = url; - - started(); - - clear(); - - Document* document = cachedPage.document(); - ASSERT(document); - document->setInPageCache(false); - - m_needsClear = true; - m_isComplete = false; - m_didCallImplicitClose = false; - m_outgoingReferrer = url.string(); - - FrameView* view = cachedPage.view(); - if (view) - view->setWasScrolledByUser(false); - m_frame->setView(view); - - m_frame->setDocument(document); - m_frame->domWindow()->setURL(document->url()); - m_frame->domWindow()->setSecurityOrigin(document->securityOrigin()); - - m_decoder = document->decoder(); - - updatePolicyBaseURL(); - - cachedPage.restore(m_frame->page()); - - checkCompleted(); -} - -bool FrameLoader::isStopping() const -{ - return activeDocumentLoader()->isStopping(); -} - -void FrameLoader::finishedLoading() -{ - // Retain because the stop may release the last reference to it. - RefPtr<Frame> protect(m_frame); - - RefPtr<DocumentLoader> dl = activeDocumentLoader(); - dl->finishedLoading(); - if (!dl->mainDocumentError().isNull() || !dl->frameLoader()) - return; - dl->setPrimaryLoadComplete(true); - m_client->dispatchDidLoadMainResource(dl.get()); - checkLoadComplete(); -} - -bool FrameLoader::isHostedByObjectElement() const -{ - HTMLFrameOwnerElement* owner = m_frame->ownerElement(); - return owner && owner->hasTagName(objectTag); -} - -bool FrameLoader::isLoadingMainFrame() const -{ - Page* page = m_frame->page(); - return page && m_frame == page->mainFrame(); -} - -bool FrameLoader::canShowMIMEType(const String& MIMEType) const -{ - return m_client->canShowMIMEType(MIMEType); -} - -bool FrameLoader::representationExistsForURLScheme(const String& URLScheme) -{ - return m_client->representationExistsForURLScheme(URLScheme); -} - -String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme) -{ - return m_client->generatedMIMETypeForURLScheme(URLScheme); -} - -void FrameLoader::cancelContentPolicyCheck() -{ - m_client->cancelPolicyCheck(); - m_policyCheck.clear(); -} - -void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame() -{ - m_client->dispatchDidReceiveServerRedirectForProvisionalLoad(); -} - -void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) -{ - // FIXME: Platforms shouldn't differ here! -#if PLATFORM(WIN) || PLATFORM(CHROMIUM) || defined(ANDROID) - if (m_creatingInitialEmptyDocument) - return; -#endif - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - // If loading a webarchive, run through webarchive machinery - const String& responseMIMEType = loader->responseMIMEType(); - - // FIXME: Mac's FrameLoaderClient::finishedLoading() method does work that is required even with Archive loads - // so we still need to call it. Other platforms should only call finishLoading for non-archive loads - // That work should be factored out so this #ifdef can be removed -#if PLATFORM(MAC) - m_client->finishedLoading(loader); - if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) - return; -#else - if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) { - m_client->finishedLoading(loader); - return; - } -#endif - - RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType)); - if (!archive) - return; - - loader->addAllArchiveResources(archive.get()); - - ArchiveResource* mainResource = archive->mainResource(); - loader->setParsedArchiveData(mainResource->data()); - continueLoadWithData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), mainResource->url()); -#else - m_client->finishedLoading(loader); -#endif -} - -bool FrameLoader::isReplacing() const -{ - return m_loadType == FrameLoadTypeReplace; -} - -void FrameLoader::setReplacing() -{ - m_loadType = FrameLoadTypeReplace; -} - -void FrameLoader::revertToProvisional(DocumentLoader* loader) -{ - m_client->revertToProvisionalState(loader); -} - -bool FrameLoader::subframeIsLoading() const -{ - // It's most likely that the last added frame is the last to load so we walk backwards. - for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) { - FrameLoader* childLoader = child->loader(); - DocumentLoader* documentLoader = childLoader->documentLoader(); - if (documentLoader && documentLoader->isLoadingInAPISense()) - return true; - documentLoader = childLoader->provisionalDocumentLoader(); - if (documentLoader && documentLoader->isLoadingInAPISense()) - return true; - } - return false; -} - -void FrameLoader::willChangeTitle(DocumentLoader* loader) -{ - m_client->willChangeTitle(loader); -} - -FrameLoadType FrameLoader::loadType() const -{ - return m_loadType; -} - -void FrameLoader::stopPolicyCheck() -{ - m_client->cancelPolicyCheck(); - PolicyCheck check = m_policyCheck; - m_policyCheck.clear(); - check.cancel(); -} - -void FrameLoader::checkLoadCompleteForThisFrame() -{ - ASSERT(m_client->hasWebView()); - - switch (m_state) { - case FrameStateProvisional: { - if (m_delegateIsHandlingProvisionalLoadError) - return; - - RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader; - if (!pdl) - return; - - // If we've received any errors we may be stuck in the provisional state and actually complete. - const ResourceError& error = pdl->mainDocumentError(); - if (error.isNull()) - return; - - // Check all children first. - RefPtr<HistoryItem> item; - if (Page* page = m_frame->page()) - if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame()) - item = m_currentHistoryItem; - - bool shouldReset = true; - if (!pdl->isLoadingInAPISense()) { - m_delegateIsHandlingProvisionalLoadError = true; - m_client->dispatchDidFailProvisionalLoad(error); - m_delegateIsHandlingProvisionalLoadError = false; - - // FIXME: can stopping loading here possibly have any effect, if isLoading is false, - // which it must be to be in this branch of the if? And is it OK to just do a full-on - // stopAllLoaders instead of stopLoadingSubframes? - stopLoadingSubframes(); - pdl->stopLoading(); - - // Finish resetting the load state, but only if another load hasn't been started by the - // delegate callback. - if (pdl == m_provisionalDocumentLoader) - clearProvisionalLoad(); - else if (m_provisionalDocumentLoader) { - KURL unreachableURL = m_provisionalDocumentLoader->unreachableURL(); - if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url()) - shouldReset = false; - } - } - if (shouldReset && item) - if (Page* page = m_frame->page()) - page->backForwardList()->goToItem(item.get()); - return; - } - - case FrameStateCommittedPage: { - DocumentLoader* dl = m_documentLoader.get(); - if (!dl || dl->isLoadingInAPISense()) - return; - - markLoadComplete(); - - // FIXME: Is this subsequent work important if we already navigated away? - // Maybe there are bugs because of that, or extra work we can skip because - // the new page is ready. - - m_client->forceLayoutForNonHTML(); - - // If the user had a scroll point, scroll to it, overriding the anchor point if any. - if (Page* page = m_frame->page()) - if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList()) - restoreScrollPositionAndViewState(); - - if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad) - return; - - const ResourceError& error = dl->mainDocumentError(); -#ifndef NDEBUG - m_didDispatchDidCommitLoad = false; -#endif - if (!error.isNull()) - m_client->dispatchDidFailLoad(error); - else - m_client->dispatchDidFinishLoad(); - - if (Page* page = m_frame->page()) - page->progress()->progressCompleted(m_frame); - -#ifdef ANDROID_INSTRUMENT - if (!m_frame->tree()->parent()) - android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize()); -#endif - return; - } - - case FrameStateComplete: - // Even if already complete, we might have set a previous item on a frame that - // didn't do any data loading on the past transaction. Make sure to clear these out. - m_client->frameLoadCompleted(); - return; - } - - ASSERT_NOT_REACHED(); -} - -void FrameLoader::continueAfterContentPolicy(PolicyAction policy) -{ - PolicyCheck check = m_policyCheck; - m_policyCheck.clear(); - check.call(policy); -} - -void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction) -{ - if (!m_provisionalDocumentLoader) - return; - - // DocumentLoader calls back to our prepareForLoadStart - m_provisionalDocumentLoader->prepareForLoadStart(); - - // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader, - // so we need to null check it again. - if (!m_provisionalDocumentLoader) - return; - - DocumentLoader* activeDocLoader = activeDocumentLoader(); - if (activeDocLoader && activeDocLoader->isLoadingMainResource()) - return; - - m_provisionalDocumentLoader->setLoadingFromCachedPage(false); - - unsigned long identifier = 0; - - if (Page* page = m_frame->page()) { - identifier = page->progress()->createUniqueIdentifier(); - dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest()); - } - - if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier)) - m_provisionalDocumentLoader->updateLoading(); -} - -void FrameLoader::didFirstLayout() -{ - if (Page* page = m_frame->page()) -#ifdef ANDROID_HISTORY_CLIENT - // this should match the logic in FrameStateCommittedPage, so that we - // can restore the scroll position and view state as early as possible - if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload) && page->backForwardList()) -#else - if (isBackForwardLoadType(m_loadType) && page->backForwardList()) -#endif - restoreScrollPositionAndViewState(); - - m_firstLayoutDone = true; - m_client->dispatchDidFirstLayout(); -} - -void FrameLoader::frameLoadCompleted() -{ - m_client->frameLoadCompleted(); - - // After a canceled provisional load, firstLayoutDone is false. - // Reset it to true if we're displaying a page. - if (m_documentLoader) - m_firstLayoutDone = true; -} - -bool FrameLoader::firstLayoutDone() const -{ - return m_firstLayoutDone; -} - -bool FrameLoader::isQuickRedirectComing() const -{ - return m_quickRedirectComing; -} - -void FrameLoader::detachChildren() -{ - // FIXME: Is it really necessary to do this in reverse order? - Frame* previous; - for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) { - previous = child->tree()->previousSibling(); - child->loader()->detachFromParent(); - } -} - -void FrameLoader::recursiveCheckLoadComplete() -{ - Vector<RefPtr<Frame>, 10> frames; - - for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling()) - frames.append(frame); - - unsigned size = frames.size(); - for (unsigned i = 0; i < size; i++) - frames[i]->loader()->recursiveCheckLoadComplete(); - - checkLoadCompleteForThisFrame(); -} - -// Called every time a resource is completely loaded, or an error is received. -void FrameLoader::checkLoadComplete() -{ - ASSERT(m_client->hasWebView()); - - // FIXME: Always traversing the entire frame tree is a bit inefficient, but - // is currently needed in order to null out the previous history item for all frames. - if (Page* page = m_frame->page()) - page->mainFrame()->loader()->recursiveCheckLoadComplete(); -} - -int FrameLoader::numPendingOrLoadingRequests(bool recurse) const -{ - if (!recurse) - return numRequests(m_frame->document()); - - int count = 0; - for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) - count += numRequests(frame->document()); - return count; -} - -FrameLoaderClient* FrameLoader::client() const -{ - return m_client; -} - -void FrameLoader::submitForm(const FrameLoadRequest& request, Event* event) -{ - // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way. - // We do not want to submit more than one form from the same page, - // nor do we want to submit a single form more than once. - // This flag prevents these from happening; not sure how other browsers prevent this. - // The flag is reset in each time we start handle a new mouse or key down event, and - // also in setView since this part may get reused for a page from the back/forward cache. - // The form multi-submit logic here is only needed when we are submitting a form that affects this frame. - // FIXME: Frame targeting is only one of the ways the submission could end up doing something other - // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly - // needed any more now that we reset m_submittedFormURL on each mouse or key down event. - Frame* target = m_frame->tree()->find(request.frameName()); - if (m_frame->tree()->isDescendantOf(target)) { - if (m_submittedFormURL == request.resourceRequest().url()) - return; - m_submittedFormURL = request.resourceRequest().url(); - } - - // FIXME: We should probably call userGestureHint() to tell whether this form submission was the result of a user gesture. - loadFrameRequestWithFormAndValues(request, false, event, m_formAboutToBeSubmitted.get(), m_formValuesAboutToBeSubmitted); - - clearRecordedFormValues(); -} - -String FrameLoader::userAgent(const KURL& url) const -{ - return m_client->userAgent(url); -} - -void FrameLoader::tokenizerProcessedData() -{ -// ASSERT(m_frame->page()); -// ASSERT(m_frame->document()); - - checkCompleted(); -} - -void FrameLoader::didTellClientAboutLoad(const String& url) -{ - m_urlsClientKnowsAbout.add(url); -} - -bool FrameLoader::haveToldClientAboutLoad(const String& url) -{ - return m_urlsClientKnowsAbout.contains(url); -} - -void FrameLoader::handledOnloadEvents() -{ - m_client->dispatchDidHandleOnloadEvents(); -} - -void FrameLoader::frameDetached() -{ - stopAllLoaders(); - detachFromParent(); -} - -void FrameLoader::detachFromParent() -{ - RefPtr<Frame> protect(m_frame); - - closeURL(); - stopAllLoaders(); - saveScrollPositionAndViewStateToItem(currentHistoryItem()); - detachChildren(); - - if (Page* page = m_frame->page()) - page->inspectorController()->frameDetachedFromParent(m_frame); - - m_client->detachedFromParent2(); - setDocumentLoader(0); - m_client->detachedFromParent3(); - if (Frame* parent = m_frame->tree()->parent()) { - parent->tree()->removeChild(m_frame); - parent->loader()->scheduleCheckCompleted(); - } else { - m_frame->setView(0); - m_frame->pageDestroyed(); - } -} - -void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, bool mainResource, bool alwaysFromRequest) -{ - applyUserAgent(request); - - if (m_loadType == FrameLoadTypeReload) { - request.setCachePolicy(ReloadIgnoringCacheData); - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - } - - // Don't set the cookie policy URL if it's already been set. - if (request.mainDocumentURL().isEmpty()) { - if (mainResource && (isLoadingMainFrame() || alwaysFromRequest)) - request.setMainDocumentURL(request.url()); - else if (Page* page = m_frame->page()) - request.setMainDocumentURL(page->mainFrame()->loader()->url()); - } - - if (mainResource) - request.setHTTPAccept("application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"); - - // Make sure we send the Origin header. - addHTTPOriginIfNeeded(request, String()); -} - -void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin) -{ - if (!request.httpOrigin().isEmpty()) - return; // Request already has an Origin header. - - // Don't send an Origin header for GET or HEAD to avoid privacy issues. - // For example, if an intranet page has a hyperlink to an external web - // site, we don't want to include the Origin of the request because it - // will leak the internal host name. Similar privacy concerns have lead - // to the widespread suppression of the Referer header at the network - // layer. - if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD") - return; - - // For non-GET and non-HEAD methods, always send an Origin header so the - // server knows we support this feature. - - if (origin.isEmpty()) { - // If we don't know what origin header to attach, we attach the value - // for an empty origin. - origin = SecurityOrigin::createEmpty()->toString(); - } - - request.setHTTPOrigin(origin); -} - -void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length) -{ -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (ArchiveFactory::isArchiveMimeType(loader->response().mimeType())) - return; -#endif - m_client->committedLoad(loader, data, length); -} - -#ifdef ANDROID_USER_GESTURE -void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, - Event* event, PassRefPtr<FormState> prpFormState, bool userGesture) -#else -void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, - Event* event, PassRefPtr<FormState> prpFormState) -#endif -{ - RefPtr<FormState> formState = prpFormState; - - // When posting, use the NSURLRequestReloadIgnoringCacheData load flag. - // This prevents a potential bug which may cause a page with a form that uses itself - // as an action to be returned from the cache without submitting. - - // FIXME: Where's the code that implements what the comment above says? - - // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a - // bunch of parameters that would come in here and then be built back up to a ResourceRequest. In case - // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest - // from scratch as it did all along. - const KURL& url = inRequest.url(); - RefPtr<FormData> formData = inRequest.httpBody(); - const String& contentType = inRequest.httpContentType(); - String origin = inRequest.httpOrigin(); - - ResourceRequest workingResourceRequest(url); -#ifdef ANDROID_USER_GESTURE - workingResourceRequest.setUserGesture(userGesture); -#endif - - if (!referrer.isEmpty()) - workingResourceRequest.setHTTPReferrer(referrer); - workingResourceRequest.setHTTPOrigin(origin); - workingResourceRequest.setHTTPMethod("POST"); - workingResourceRequest.setHTTPBody(formData); - workingResourceRequest.setHTTPContentType(contentType); - addExtraFieldsToRequest(workingResourceRequest, true, true); - - NavigationAction action(url, FrameLoadTypeStandard, true, event); - - if (!frameName.isEmpty()) { - if (Frame* targetFrame = findFrameForNavigation(frameName)) - targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release()); - else - checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName); - } else - loadWithNavigationAction(workingResourceRequest, action, FrameLoadTypeStandard, formState.release()); -} - -bool FrameLoader::isReloading() const -{ - return documentLoader()->request().cachePolicy() == ReloadIgnoringCacheData; -} - -void FrameLoader::loadEmptyDocumentSynchronously() -{ - ResourceRequest request(KURL("")); - load(request); -} - -unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data) -{ - // Since this is a subresource, we can load any URL (we ignore the return value). - // But we still want to know whether we should hide the referrer or not, so we call the canLoad method. - String referrer = m_outgoingReferrer; - if (shouldHideReferrer(request.url(), referrer)) - referrer = String(); - - ResourceRequest initialRequest = request; - initialRequest.setTimeoutInterval(10); - - if (initialRequest.isConditional()) - initialRequest.setCachePolicy(ReloadIgnoringCacheData); - else - initialRequest.setCachePolicy(documentLoader()->request().cachePolicy()); - - if (!referrer.isEmpty()) - initialRequest.setHTTPReferrer(referrer); - addHTTPOriginIfNeeded(initialRequest, outgoingOrigin()); - - if (Page* page = m_frame->page()) - initialRequest.setMainDocumentURL(page->mainFrame()->loader()->documentLoader()->request().url()); - initialRequest.setHTTPUserAgent(client()->userAgent(request.url())); - - unsigned long identifier = 0; - ResourceRequest newRequest(initialRequest); - requestFromDelegate(newRequest, identifier, error); - - if (error.isNull()) { - ASSERT(!newRequest.isNull()); - didTellClientAboutLoad(newRequest.url().string()); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - ApplicationCacheResource* resource; - if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) { - if (resource) { - response = resource->response(); - data.append(resource->data()->data(), resource->data()->size()); - } else - error = cannotShowURLError(newRequest); - } else -#endif - ResourceHandle::loadResourceSynchronously(newRequest, error, response, data, m_frame); - } - - sendRemainingDelegateMessages(identifier, response, data.size(), error); - return identifier; -} - -void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest) -{ - return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest); -} - -void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse) -{ - applyUserAgent(clientRequest); - dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse); -} - -void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r) -{ - activeDocumentLoader()->addResponse(r); - - if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), r); - dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r); -} - -void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived) -{ - if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), data, length); - dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived); -} - -void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - if (!error.isNull()) - m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error); -} - -const ResourceRequest& FrameLoader::originalRequest() const -{ - return activeDocumentLoader()->originalRequestCopy(); -} - -void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete) -{ - // Retain because the stop may release the last reference to it. - RefPtr<Frame> protect(m_frame); - - RefPtr<DocumentLoader> loader = activeDocumentLoader(); - - if (isComplete) { - // FIXME: Don't want to do this if an entirely new load is going, so should check - // that both data sources on the frame are either this or nil. - stop(); - if (m_client->shouldFallBack(error)) - handleFallbackContent(); - } - - if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) { - KURL failedURL = m_provisionalDocumentLoader->originalRequestCopy().url(); - didNotOpenURL(failedURL); - - // We might have made a page cache item, but now we're bailing out due to an error before we ever - // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state - // so that the existing view (that wenever got far enough to replace) can continue being used. - invalidateCurrentItemCachedPage(); - - // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's - // status has changed, if there was a redirect. The frame load delegate may have saved some state about - // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely - // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect - // has ended. - if (m_sentRedirectNotification) - clientRedirectCancelledOrFinished(false); - } - - - loader->mainReceivedError(error, isComplete); -} - -void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument, - const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) -{ - FrameLoader* loader = static_cast<FrameLoader*>(argument); - loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue); -} - -void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue) -{ - // FIXME: - // some functions check m_quickRedirectComing, and others check for - // FrameLoadTypeRedirectWithLockedHistory. - bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedHistory; - m_quickRedirectComing = false; - - if (!shouldContinue) - return; - - KURL url = request.url(); - - m_documentLoader->replaceRequestURLForAnchorScroll(url); - if (!isRedirect && !shouldTreatURLAsSameAsCurrent(url)) { - // NB: must happen after _setURL, since we add based on the current request. - // Must also happen before we openURL and displace the scroll position, since - // adding the BF item will save away scroll state. - - // NB2: If we were loading a long, slow doc, and the user anchor nav'ed before - // it was done, currItem is now set the that slow doc, and prevItem is whatever was - // before it. Adding the b/f item will bump the slow doc down to prevItem, even - // though its load is not yet done. I think this all works out OK, for one because - // we have already saved away the scroll and doc state for the long slow load, - // but it's not an obvious case. - - addHistoryItemForFragmentScroll(); - } - - scrollToAnchor(url); - - if (!isRedirect) - // This will clear previousItem from the rest of the frame tree that didn't - // doing any loading. We need to make a pass on this now, since for anchor nav - // we'll not go through a real load and reach Completed state. - checkLoadComplete(); - - m_client->dispatchDidChangeLocationWithinPage(); - m_client->didFinishLoad(); -} - -bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url) -{ - // Should we do anchor navigation within the existing content? - - // We don't do this if we are submitting a form, explicitly reloading, - // currently displaying a frameset, or if the URL does not have a fragment. - // These rules were originally based on what KHTML was doing in KHTMLPart::openURL. - - // FIXME: What about load types other than Standard and Reload? - - return !isFormSubmission - && loadType != FrameLoadTypeReload - && loadType != FrameLoadTypeSame - && !shouldReload(this->url(), url) - // We don't want to just scroll if a link from within a - // frameset is trying to reload the frameset into _top. - && !m_frame->isFrameSet(); -} - -void FrameLoader::opened() -{ - if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect()) - updateHistoryForClientRedirect(); - - if (m_documentLoader->isLoadingFromCachedPage()) { - m_frame->document()->documentDidBecomeActive(); - - // Force a layout to update view size and thereby update scrollbars. - m_client->forceLayout(); - - const ResponseVector& responses = m_documentLoader->responses(); - size_t count = responses.size(); - for (size_t i = 0; i < count; i++) { - const ResourceResponse& response = responses[i]; - // FIXME: If the WebKit client changes or cancels the request, this is not respected. - ResourceError error; - unsigned long identifier; - ResourceRequest request(response.url()); - requestFromDelegate(request, identifier, error); - // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. - // However, with today's computers and networking speeds, this won't happen in practice. - // Could be an issue with a giant local file. - sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error); - } - - pageCache()->remove(m_currentHistoryItem.get()); - - m_documentLoader->setPrimaryLoadComplete(true); - - // FIXME: Why only this frame and not parent frames? - checkLoadCompleteForThisFrame(); - } -} - -void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request, - PassRefPtr<FormState> formState, const String& frameName) -{ - m_policyCheck.set(request, formState, frameName, - callContinueLoadAfterNewWindowPolicy, this); - m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy, - action, request, formState, frameName); -} - -void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy) -{ - PolicyCheck check = m_policyCheck; - m_policyCheck.clear(); - - switch (policy) { - case PolicyIgnore: - check.clearRequest(); - break; - case PolicyDownload: - m_client->startDownload(check.request()); - check.clearRequest(); - break; - case PolicyUse: - break; - } - - check.call(policy == PolicyUse); -} - -void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader, - PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument) -{ - NavigationAction action = loader->triggeringAction(); - if (action.isEmpty()) { - action = NavigationAction(request.url(), NavigationTypeOther); - loader->setTriggeringAction(action); - } - - // Don't ask more than once for the same request or if we are loading an empty URL. - // This avoids confusion on the part of the client. - if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) { - function(argument, request, 0, true); - loader->setLastCheckedRequest(request); - return; - } - - // We are always willing to show alternate content for unreachable URLs; - // treat it like a reload so it maintains the right state for b/f list. - if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) { - if (isBackForwardLoadType(m_policyLoadType)) - m_policyLoadType = FrameLoadTypeReload; - function(argument, request, 0, true); - return; - } - - loader->setLastCheckedRequest(request); - - m_policyCheck.set(request, formState.get(), function, argument); - - m_delegateIsDecidingNavigationPolicy = true; - m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy, - action, request, formState); - m_delegateIsDecidingNavigationPolicy = false; -} - -void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy) -{ - PolicyCheck check = m_policyCheck; - m_policyCheck.clear(); - - bool shouldContinue = policy == PolicyUse; - - switch (policy) { - case PolicyIgnore: - check.clearRequest(); - break; - case PolicyDownload: - m_client->startDownload(check.request()); - check.clearRequest(); - break; - case PolicyUse: { - ResourceRequest request(check.request()); - - if (!m_client->canHandleRequest(request)) { - handleUnimplementablePolicy(m_client->cannotShowURLError(check.request())); - check.clearRequest(); - shouldContinue = false; - } - break; - } - } - - check.call(shouldContinue); -} - -void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument, - const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue) -{ - FrameLoader* loader = static_cast<FrameLoader*>(argument); - loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue); -} - -void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue) -{ - // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a - // nil policyDataSource because loading the alternate page will have passed - // through this method already, nested; otherwise, policyDataSource should still be set. - ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty()); - - bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false; - - // Two reasons we can't continue: - // 1) Navigation policy delegate said we can't so request is nil. A primary case of this - // is the user responding Cancel to the form repost nag sheet. - // 2) User responded Cancel to an alert popped up by the before unload event handler. - // The "before unload" event handler runs only for the main frame. - bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose()); - - if (!canContinue) { - // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we - // need to report that the client redirect was cancelled. - if (m_quickRedirectComing) - clientRedirectCancelledOrFinished(false); - - setPolicyDocumentLoader(0); - - // If the navigation request came from the back/forward menu, and we punt on it, we have the - // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity, - // we only do this when punting a navigation for the target frame or top-level frame. - if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType)) - if (Page* page = m_frame->page()) { - Frame* mainFrame = page->mainFrame(); - if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) - page->backForwardList()->goToItem(resetItem); - } - return; - } - - FrameLoadType type = m_policyLoadType; - stopAllLoaders(); - - // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders() - // might detach the current FrameLoader, in which case we should bail on this newly defunct load. - if (!m_frame->page()) - return; - - setProvisionalDocumentLoader(m_policyDocumentLoader.get()); - m_loadType = type; - setState(FrameStateProvisional); - - setPolicyDocumentLoader(0); - - if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage()) - return; - - if (formState) - m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState); - else - continueLoadAfterWillSubmitForm(); -} - - -void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument, - const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue) -{ - FrameLoader* loader = static_cast<FrameLoader*>(argument); - loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue); -} - -void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request, - PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue) -{ - if (!shouldContinue) - return; - - RefPtr<Frame> frame = m_frame; - RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(); - if (!mainFrame) - return; - - if (frameName != "_blank") - mainFrame->tree()->setName(frameName); - - mainFrame->loader()->setOpenedByDOM(); - mainFrame->loader()->m_client->dispatchShow(); - mainFrame->loader()->setOpener(frame.get()); - mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), FrameLoadTypeStandard, formState); -} - -void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error) -{ - if (!response.isNull()) - dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response); - - if (length > 0) - dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length); - - if (error.isNull()) - dispatchDidFinishLoading(m_documentLoader.get(), identifier); - else - m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error); -} - -void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error) -{ - ASSERT(!request.isNull()); - - identifier = 0; - if (Page* page = m_frame->page()) { - identifier = page->progress()->createUniqueIdentifier(); - dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request); - } - - ResourceRequest newRequest(request); - dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse()); - - if (newRequest.isNull()) - error = cancelledError(request); - else - error = ResourceError(); - - request = newRequest; -} - -void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource) -{ - ResourceRequest request(resource->url()); - const ResourceResponse& response = resource->response(); - SharedBuffer* data = resource->data(); - int length = data ? data->size() : 0; - - if (Page* page = m_frame->page()) - page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length); - - if (!resource->sendResourceLoadCallbacks() || haveToldClientAboutLoad(resource->url())) - return; - - if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length)) { - didTellClientAboutLoad(resource->url()); - return; - } - - unsigned long identifier; - ResourceError error; - ResourceRequest r(request); - requestFromDelegate(r, identifier, error); - sendRemainingDelegateMessages(identifier, response, length, error); - - didTellClientAboutLoad(resource->url()); -} - -void FrameLoader::applyUserAgent(ResourceRequest& request) -{ - String userAgent = client()->userAgent(request.url()); - ASSERT(!userAgent.isNull()); - request.setHTTPUserAgent(userAgent); -} - -bool FrameLoader::canGoBackOrForward(int distance) const -{ - if (Page* page = m_frame->page()) { - if (distance == 0) - return true; - if (distance > 0 && distance <= page->backForwardList()->forwardListCount()) - return true; - if (distance < 0 && -distance <= page->backForwardList()->backListCount()) - return true; - } - return false; -} - -int FrameLoader::getHistoryLength() -{ - if (Page* page = m_frame->page()) - return page->backForwardList()->backListCount() + 1; - return 0; -} - -KURL FrameLoader::historyURL(int distance) -{ - if (Page* page = m_frame->page()) { - BackForwardList* list = page->backForwardList(); - HistoryItem* item = list->itemAtIndex(distance); - if (!item) { - if (distance > 0) { - int forwardListCount = list->forwardListCount(); - if (forwardListCount > 0) - item = list->itemAtIndex(forwardListCount); - } else { - int backListCount = list->backListCount(); - if (backListCount > 0) - item = list->itemAtIndex(-backListCount); - } - } - if (item) - return item->url(); - } - return KURL(); -} - -void FrameLoader::addHistoryItemForFragmentScroll() -{ - addBackForwardItemClippedAtTarget(false); -} - -bool FrameLoader::loadProvisionalItemFromCachedPage() -{ - RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get()); - if (!cachedPage || !cachedPage->document()) - return false; - provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release()); - return true; -} - -void FrameLoader::cachePageForHistoryItem(HistoryItem* item) -{ - if (Page* page = m_frame->page()) { - RefPtr<CachedPage> cachedPage = CachedPage::create(page); - cachedPage->setTimeStampToNow(); - cachedPage->setDocumentLoader(documentLoader()); - m_client->savePlatformDataToCachedPage(cachedPage.get()); - - pageCache()->add(item, cachedPage.release()); - } -} - -bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const -{ - if (!m_currentHistoryItem) - return false; - return url == m_currentHistoryItem->url() || url == m_currentHistoryItem->originalURL(); -} - -PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal) -{ - DocumentLoader* docLoader = documentLoader(); - - KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL(); - - KURL url; - KURL originalURL; - - if (!unreachableURL.isEmpty()) { - url = unreachableURL; - originalURL = unreachableURL; - } else { - originalURL = docLoader ? docLoader->originalURL() : KURL(); - if (useOriginal) - url = originalURL; - else if (docLoader) - url = docLoader->requestURL(); - } - - LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data()); - - // Frames that have never successfully loaded any content - // may have no URL at all. Currently our history code can't - // deal with such things, so we nip that in the bud here. - // Later we may want to learn to live with nil for URL. - // See bug 3368236 and related bugs for more information. - if (url.isEmpty()) - url = blankURL(); - if (originalURL.isEmpty()) - originalURL = blankURL(); - - Frame* parentFrame = m_frame->tree()->parent(); - String parent = parentFrame ? parentFrame->tree()->name() : ""; - String title = docLoader ? docLoader->title() : ""; - - RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title); - item->setOriginalURLString(originalURL.string()); - - // Save form state if this is a POST - if (docLoader) { - if (useOriginal) - item->setFormInfoFromRequest(docLoader->originalRequest()); - else - item->setFormInfoFromRequest(docLoader->request()); - } - - // Set the item for which we will save document state - m_previousHistoryItem = m_currentHistoryItem; - m_currentHistoryItem = item; - - return item.release(); -} - -void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip) -{ - Page* page = m_frame->page(); - if (!page) - return; - - if (documentLoader()->urlForHistory().isEmpty()) - return; - - Frame* mainFrame = page->mainFrame(); - ASSERT(mainFrame); - FrameLoader* frameLoader = mainFrame->loader(); - - if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) { - frameLoader->m_didPerformFirstNavigation = true; - m_client->didPerformFirstNavigation(); - } - - RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip); - LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->url().string().ascii().data()); - page->backForwardList()->addItem(item); -} - -PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget) -{ - RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false); - if (m_previousHistoryItem) - saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get()); - if (!(clipAtTarget && m_frame == targetFrame)) { - // save frame state for items that aren't loading (khtml doesn't save those) - saveDocumentState(); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { - FrameLoader* childLoader = child->loader(); - bool hasChildLoaded = childLoader->frameHasLoaded(); - - // If the child is a frame corresponding to an <object> element that never loaded, - // we don't want to create a history item, because that causes fallback content - // to be ignored on reload. - - if (!(!hasChildLoaded && childLoader->isHostedByObjectElement())) - bfItem->addChildItem(childLoader->createHistoryItemTree(targetFrame, clipAtTarget)); - } - } - if (m_frame == targetFrame) - bfItem->setIsTargetItem(true); - return bfItem; -} - -Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) -{ - Frame* frame = m_frame->tree()->find(name); - if (shouldAllowNavigation(frame)) - return frame; - return 0; -} - -void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item) -{ - if (!item || !m_frame->view()) - return; - - item->setScrollPoint(m_frame->view()->scrollPosition()); - // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client. - m_client->saveViewStateToItem(item); -} - -/* - There is a race condition between the layout and load completion that affects restoring the scroll position. - We try to restore the scroll position at both the first layout and upon load completion. - - 1) If first layout happens before the load completes, we want to restore the scroll position then so that the - first time we draw the page is already scrolled to the right place, instead of starting at the top and later - jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in - which case the restore silent fails and we will fix it in when we try to restore on doc completion. - 2) If the layout happens after the load completes, the attempt to restore at load completion time silently - fails. We then successfully restore it when the layout happens. -*/ -void FrameLoader::restoreScrollPositionAndViewState() -{ - if (!m_committedFirstRealDocumentLoad) - return; - - ASSERT(m_currentHistoryItem); - - // FIXME: As the ASSERT attests, it seems we should always have a currentItem here. - // One counterexample is <rdar://problem/4917290> - // For now, to cover this issue in release builds, there is no technical harm to returning - // early and from a user standpoint - as in the above radar - the previous page load failed - // so there *is* no scroll or view state to restore! - if (!m_currentHistoryItem) - return; - - // FIXME: It would be great to work out a way to put this code in WebCore instead of calling - // through to the client. It's currently used only for the PDF view on Mac. - m_client->restoreViewState(); - - if (FrameView* view = m_frame->view()) - if (!view->wasScrolledByUser()) - view->setScrollPosition(m_currentHistoryItem->scrollPoint()); -} - -void FrameLoader::invalidateCurrentItemCachedPage() -{ - // When we are pre-commit, the currentItem is where the pageCache data resides - CachedPage* cachedPage = pageCache()->get(m_currentHistoryItem.get()); - - // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach - // Somehow the PageState object is not properly updated, and is holding onto a stale document. - // Both Xcode and FileMaker see this crash, Safari does not. - - ASSERT(!cachedPage || cachedPage->document() == m_frame->document()); - if (cachedPage && cachedPage->document() == m_frame->document()) { - cachedPage->document()->setInPageCache(false); - cachedPage->clear(); - } - - if (cachedPage) - pageCache()->remove(m_currentHistoryItem.get()); -} - -void FrameLoader::saveDocumentState() -{ - if (m_creatingInitialEmptyDocument) - return; - - // For a standard page load, we will have a previous item set, which will be used to - // store the form state. However, in some cases we will have no previous item, and - // the current item is the right place to save the state. One example is when we - // detach a bunch of frames because we are navigating from a site with frames to - // another site. Another is when saving the frame state of a frame that is not the - // target of the current navigation (if we even decide to save with that granularity). - - // Because of previousItem's "masking" of currentItem for this purpose, it's important - // that previousItem be cleared at the end of a page transition. We leverage the - // checkLoadComplete recursion to achieve this goal. - - HistoryItem* item = m_previousHistoryItem ? m_previousHistoryItem.get() : m_currentHistoryItem.get(); - if (!item) - return; - - Document* document = m_frame->document(); - ASSERT(document); - - if (document && item->isCurrentDocument(document)) { - LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item); - item->setDocumentState(document->formElementsState()); - } -} - -// Loads content into this frame, as specified by history item -void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) -{ - if (!m_frame->page()) - return; - - KURL itemURL = item->url(); - KURL itemOriginalURL = item->originalURL(); - KURL currentURL; - if (documentLoader()) - currentURL = documentLoader()->url(); - RefPtr<FormData> formData = item->formData(); - - // Are we navigating to an anchor within the page? - // Note if we have child frames we do a real reload, since the child frames might not - // match our current frame structure, or they might not have the right content. We could - // check for all that as an additional optimization. - // We also do not do anchor-style navigation if we're posting a form. - - if (!formData && urlsMatchItem(item)) { - // Must do this maintenance here, since we don't go through a real page reload - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); - - if (FrameView* view = m_frame->view()) - view->setWasScrolledByUser(false); - - m_currentHistoryItem = item; - - // FIXME: Form state might need to be saved here too. - - // We always call scrollToAnchor here, even if the URL doesn't have an - // anchor fragment. This is so we'll keep the WebCore Frame's URL up-to-date. - scrollToAnchor(item->url()); - - // must do this maintenance here, since we don't go through a real page reload - restoreScrollPositionAndViewState(); - - // Fake the URL change by updating the data source's request. This will no longer - // be necessary if we do the better fix described above. - documentLoader()->replaceRequestURLForAnchorScroll(itemURL); - - m_client->dispatchDidChangeLocationWithinPage(); - - // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error - m_client->didFinishLoad(); - } else { - // Remember this item so we can traverse any child items as child frames load - m_provisionalHistoryItem = item; - - bool inPageCache = false; - - // Check if we'll be using the page cache. We only use the page cache - // if one exists and it is less than _backForwardCacheExpirationInterval - // seconds old. If the cache is expired it gets flushed here. - if (RefPtr<CachedPage> cachedPage = pageCache()->get(item)) { - double interval = currentTime() - cachedPage->timeStamp(); - - // FIXME: 1800 should not be hardcoded, it should come from - // WebKitBackForwardCacheExpirationIntervalKey in WebKit. - // Or we should remove WebKitBackForwardCacheExpirationIntervalKey. - if (interval <= 1800) { - loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0); - inPageCache = true; - } else { - LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", m_provisionalHistoryItem->url().string().ascii().data()); - pageCache()->remove(item); - } - } - - if (!inPageCache) { - ResourceRequest request(itemURL); - - // If this was a repost that failed the page cache, we might try to repost the form. - NavigationAction action; - if (formData) { - - formData->generateFiles(m_frame->page()->chrome()->client()); - - request.setHTTPMethod("POST"); - request.setHTTPReferrer(item->formReferrer()); - request.setHTTPBody(formData); - request.setHTTPContentType(item->formContentType()); - RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->formReferrer()); - addHTTPOriginIfNeeded(request, securityOrigin->toString()); - - // FIXME: Slight hack to test if the NSURL cache contains the page we're going to. - // We want to know this before talking to the policy delegate, since it affects whether - // we show the DoYouReallyWantToRepost nag. - // - // This trick has a small bug (3123893) where we might find a cache hit, but then - // have the item vanish when we try to use it in the ensuing nav. This should be - // extremely rare, but in that case the user will get an error on the navigation. - - if (ResourceHandle::willLoadFromCache(request)) - action = NavigationAction(itemURL, loadType, false); - else { - request.setCachePolicy(ReloadIgnoringCacheData); - action = NavigationAction(itemURL, NavigationTypeFormResubmitted); - } - } else { - switch (loadType) { - case FrameLoadTypeReload: - request.setCachePolicy(ReloadIgnoringCacheData); - break; - case FrameLoadTypeBack: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - if (itemURL.protocol() != "https") - request.setCachePolicy(ReturnCacheDataElseLoad); - break; - case FrameLoadTypeStandard: - case FrameLoadTypeRedirectWithLockedHistory: - // no-op: leave as protocol default - // FIXME: I wonder if we ever hit this case - break; - case FrameLoadTypeSame: - case FrameLoadTypeReloadAllowingStaleData: - default: - ASSERT_NOT_REACHED(); - } - - action = NavigationAction(itemOriginalURL, loadType, false); - } - - addExtraFieldsToRequest(request, true, formData); - loadWithNavigationAction(request, action, loadType, 0); - } - } -} - -// Walk the frame tree and ensure that the URLs match the URLs in the item. -bool FrameLoader::urlsMatchItem(HistoryItem* item) const -{ - const KURL& currentURL = documentLoader()->url(); - if (!equalIgnoringRef(currentURL, item->url())) - return false; - - const HistoryItemVector& childItems = item->children(); - - unsigned size = childItems.size(); - for (unsigned i = 0; i < size; ++i) { - Frame* childFrame = m_frame->tree()->child(childItems[i]->target()); - if (childFrame && !childFrame->loader()->urlsMatchItem(childItems[i].get())) - return false; - } - - return true; -} - -// Main funnel for navigating to a previous location (back/forward, non-search snap-back) -// This includes recursion to handle loading into framesets properly -void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type) -{ - ASSERT(!m_frame->tree()->parent()); - - // shouldGoToHistoryItem is a private delegate method. This is needed to fix: - // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls - // Ultimately, history item navigations should go through the policy delegate. That's covered in: - // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate - Page* page = m_frame->page(); - if (!page) - return; - if (!m_client->shouldGoToHistoryItem(targetItem)) - return; - - // Set the BF cursor before commit, which lets the user quickly click back/forward again. - // - plus, it only makes sense for the top level of the operation through the frametree, - // as opposed to happening for some/one of the page commits that might happen soon - BackForwardList* bfList = page->backForwardList(); - HistoryItem* currentItem = bfList->currentItem(); - bfList->goToItem(targetItem); - recursiveGoToItem(targetItem, currentItem, type); -} - -// The general idea here is to traverse the frame tree and the item tree in parallel, -// tracking whether each frame already has the content the item requests. If there is -// a match (by URL), we just restore scroll position and recurse. Otherwise we must -// reload that frame, and all its kids. -void FrameLoader::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) -{ - ASSERT(item); - ASSERT(fromItem); - - KURL itemURL = item->url(); - KURL currentURL; - if (documentLoader()) - currentURL = documentLoader()->url(); - - // Always reload the target frame of the item we're going to. This ensures that we will - // do -some- load for the transition, which means a proper notification will be posted - // to the app. - // The exact URL has to match, including fragment. We want to go through the _load - // method, even if to do a within-page navigation. - // The current frame tree and the frame tree snapshot in the item have to match. - if (!item->isTargetItem() && - itemURL == currentURL && - ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) && - childFramesMatchItem(item)) - { - // This content is good, so leave it alone and look for children that need reloading - // Save form state (works from currentItem, since prevItem is nil) - ASSERT(!m_previousHistoryItem); - saveDocumentState(); - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); - - if (FrameView* view = m_frame->view()) - view->setWasScrolledByUser(false); - - m_currentHistoryItem = item; - - // Restore form state (works from currentItem) - restoreDocumentState(); - - // Restore the scroll position (we choose to do this rather than going back to the anchor point) - restoreScrollPositionAndViewState(); - - const HistoryItemVector& childItems = item->children(); - - int size = childItems.size(); - for (int i = 0; i < size; ++i) { - String childName = childItems[i]->target(); - HistoryItem* fromChildItem = fromItem->childItemWithName(childName); - ASSERT(fromChildItem || fromItem->isTargetItem()); - Frame* childFrame = m_frame->tree()->child(childName); - ASSERT(childFrame); - childFrame->loader()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); - } - } else { - loadItem(item, type); - } -} - -// helper method that determines whether the subframes described by the item's subitems -// match our own current frameset -bool FrameLoader::childFramesMatchItem(HistoryItem* item) const -{ - const HistoryItemVector& childItems = item->children(); - if (childItems.size() != m_frame->tree()->childCount()) - return false; - - unsigned size = childItems.size(); - for (unsigned i = 0; i < size; ++i) - if (!m_frame->tree()->child(childItems[i]->target())) - return false; - - // Found matches for all item targets - return true; -} - -// There are 3 things you might think of as "history", all of which are handled by these functions. -// -// 1) Back/forward: The m_currentHistoryItem is part of this mechanism. -// 2) Global history: Handled by the client. -// 3) Visited links: Handled by the PageGroup. - -void FrameLoader::updateHistoryForStandardLoad() -{ - LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->url().string().ascii().data()); - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - // If the navigation occured during load and this is a subframe, update the current - // back/forward item rather than adding a new one and don't add the new URL to global - // history at all. But do add it to visited links. <rdar://problem/5333496> - bool frameNavigationDuringLoad = false; - if (m_navigationDuringLoad) { - HTMLFrameOwnerElement* owner = m_frame->ownerElement(); - frameNavigationDuringLoad = owner && !owner->createdByParser(); - m_navigationDuringLoad = false; - } - - if (!frameNavigationDuringLoad && !documentLoader()->isClientRedirect()) { - if (!historyURL.isEmpty()) { - addBackForwardItemClippedAtTarget(true); - if (!needPrivacy) - m_client->updateGlobalHistory(historyURL); - } - } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) { - m_currentHistoryItem->setURL(documentLoader()->url()); - m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - } -} - -void FrameLoader::updateHistoryForClientRedirect() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", documentLoader()->title().utf8().data()); -#endif - - // Clear out form data so we don't try to restore it into the incoming page. Must happen after - // webcore has closed the URL and saved away the form state. - if (m_currentHistoryItem) { - m_currentHistoryItem->clearDocumentState(); - m_currentHistoryItem->clearScrollPoint(); - } - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - } -} - -void FrameLoader::updateHistoryForBackForwardNavigation() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", documentLoader()->title().utf8().data()); -#endif - - // Must grab the current scroll position before disturbing it - saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get()); -} - -void FrameLoader::updateHistoryForReload() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for reload in frame %s", documentLoader()->title().utf8().data()); -#endif - - if (m_currentHistoryItem) { - pageCache()->remove(m_currentHistoryItem.get()); - - if (loadType() == FrameLoadTypeReload) - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); - - // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072 - if (documentLoader()->unreachableURL().isEmpty()) - m_currentHistoryItem->setURL(documentLoader()->requestURL()); - } -} - -void FrameLoader::updateHistoryForRedirectWithLockedHistory() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for internal load in frame %s", documentLoader()->title().utf8().data()); -#endif - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - if (documentLoader()->isClientRedirect()) { - if (!m_currentHistoryItem && !m_frame->tree()->parent()) { - addBackForwardItemClippedAtTarget(true); - if (!needPrivacy && !historyURL.isEmpty()) - m_client->updateGlobalHistory(historyURL); - } - if (m_currentHistoryItem) { - m_currentHistoryItem->setURL(documentLoader()->url()); - m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); - } - } else { - Frame* parentFrame = m_frame->tree()->parent(); - if (parentFrame && parentFrame->loader()->m_currentHistoryItem) - parentFrame->loader()->m_currentHistoryItem->addChildItem(createHistoryItem(true)); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - } -} - -void FrameLoader::updateHistoryForCommit() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for commit in frame %s", documentLoader()->title().utf8().data()); -#endif - FrameLoadType type = loadType(); - if (isBackForwardLoadType(type) || - (type == FrameLoadTypeReload && !provisionalDocumentLoader()->unreachableURL().isEmpty())) { - // Once committed, we want to use current item for saving DocState, and - // the provisional item for restoring state. - // Note previousItem must be set before we close the URL, which will - // happen when the data source is made non-provisional below - m_previousHistoryItem = m_currentHistoryItem; - ASSERT(m_provisionalHistoryItem); - m_currentHistoryItem = m_provisionalHistoryItem; - m_provisionalHistoryItem = 0; - } -} - -void FrameLoader::updateHistoryForAnchorScroll() -{ - if (m_URL.isEmpty()) - return; - - Settings* settings = m_frame->settings(); - if (!settings || settings->privateBrowsingEnabled()) - return; - - Page* page = m_frame->page(); - if (!page) - return; - - page->group().addVisitedLink(m_URL); -} - -// Walk the frame tree, telling all frames to save their form state into their current -// history item. -void FrameLoader::saveDocumentAndScrollState() -{ - for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) { - frame->loader()->saveDocumentState(); - frame->loader()->saveScrollPositionAndViewStateToItem(frame->loader()->currentHistoryItem()); - } -} - -// FIXME: These 6 setter/getters are here for a dwindling number of users in WebKit, WebFrame -// being the primary one. After they're no longer needed there, they can be removed! -HistoryItem* FrameLoader::currentHistoryItem() -{ - return m_currentHistoryItem.get(); -} - -HistoryItem* FrameLoader::previousHistoryItem() -{ - return m_previousHistoryItem.get(); -} - -HistoryItem* FrameLoader::provisionalHistoryItem() -{ - return m_provisionalHistoryItem.get(); -} - -void FrameLoader::setCurrentHistoryItem(PassRefPtr<HistoryItem> item) -{ - m_currentHistoryItem = item; -} - -void FrameLoader::setPreviousHistoryItem(PassRefPtr<HistoryItem> item) -{ - m_previousHistoryItem = item; -} - -void FrameLoader::setProvisionalHistoryItem(PassRefPtr<HistoryItem> item) -{ - m_provisionalHistoryItem = item; -} - -void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error) -{ - m_client->setMainDocumentError(loader, error); -} - -void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError& error) -{ - loader->setPrimaryLoadComplete(true); - m_client->dispatchDidLoadMainResource(activeDocumentLoader()); - checkCompleted(); - if (m_frame->page()) - checkLoadComplete(); -} - -void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete) -{ - activeDocumentLoader()->mainReceivedError(error, isComplete); -} - -ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const -{ - ResourceError error = m_client->cancelledError(request); - error.setIsCancellation(true); - return error; -} - -ResourceError FrameLoader::blockedError(const ResourceRequest& request) const -{ - return m_client->blockedError(request); -} - -ResourceError FrameLoader::cannotShowURLError(const ResourceRequest& request) const -{ - return m_client->cannotShowURLError(request); -} - -ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const -{ - return m_client->fileDoesNotExistError(response); -} - -void FrameLoader::didFinishLoad(ResourceLoader* loader) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - dispatchDidFinishLoading(loader->documentLoader(), loader->identifier()); -} - -void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_client->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - -void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_client->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - -PolicyCheck::PolicyCheck() - : m_navigationFunction(0) - , m_newWindowFunction(0) - , m_contentFunction(0) -{ -} - -void PolicyCheck::clear() -{ - clearRequest(); - m_navigationFunction = 0; - m_newWindowFunction = 0; - m_contentFunction = 0; -} - -void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState, - NavigationPolicyDecisionFunction function, void* argument) -{ - m_request = request; - m_formState = formState; - m_frameName = String(); - - m_navigationFunction = function; - m_newWindowFunction = 0; - m_contentFunction = 0; - m_argument = argument; -} - -void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState, - const String& frameName, NewWindowPolicyDecisionFunction function, void* argument) -{ - m_request = request; - m_formState = formState; - m_frameName = frameName; - - m_navigationFunction = 0; - m_newWindowFunction = function; - m_contentFunction = 0; - m_argument = argument; -} - -void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument) -{ - m_request = ResourceRequest(); - m_formState = 0; - m_frameName = String(); - - m_navigationFunction = 0; - m_newWindowFunction = 0; - m_contentFunction = function; - m_argument = argument; -} - -void PolicyCheck::call(bool shouldContinue) -{ - if (m_navigationFunction) - m_navigationFunction(m_argument, m_request, m_formState.get(), shouldContinue); - if (m_newWindowFunction) - m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, shouldContinue); - ASSERT(!m_contentFunction); -} - -void PolicyCheck::call(PolicyAction action) -{ - ASSERT(!m_navigationFunction); - ASSERT(!m_newWindowFunction); - ASSERT(m_contentFunction); - m_contentFunction(m_argument, action); -} - -void PolicyCheck::clearRequest() -{ - m_request = ResourceRequest(); - m_formState = 0; - m_frameName = String(); -} - -void PolicyCheck::cancel() -{ - clearRequest(); - if (m_navigationFunction) - m_navigationFunction(m_argument, m_request, m_formState.get(), false); - if (m_newWindowFunction) - m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, false); - if (m_contentFunction) - m_contentFunction(m_argument, PolicyIgnore); -} - -void FrameLoader::setTitle(const String& title) -{ - documentLoader()->setTitle(title); -} - -KURL FrameLoader::originalRequestURL() const -{ - return activeDocumentLoader()->originalRequest().url(); -} - -String FrameLoader::referrer() const -{ - return documentLoader()->request().httpReferrer(); -} - -void FrameLoader::dispatchWindowObjectAvailable() -{ - if (!m_frame->script()->isEnabled() || !m_frame->script()->haveWindowShell()) - return; - - m_client->windowObjectCleared(); - - if (Page* page = m_frame->page()) { - if (InspectorController* inspector = page->inspectorController()) - inspector->inspectedWindowScriptObjectCleared(m_frame); - if (InspectorController* inspector = page->parentInspectorController()) - inspector->windowScriptObjectAvailable(); - } -} - -Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* element, const HashMap<String, String>& args) -{ - String baseURLString; - Vector<String> paramNames; - Vector<String> paramValues; - HashMap<String, String>::const_iterator end = args.end(); - for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) { - if (equalIgnoringCase(it->first, "baseurl")) - baseURLString = it->second; - paramNames.append(it->first); - paramValues.append(it->second); - } - - if (baseURLString.isEmpty()) - baseURLString = m_frame->document()->baseURL().string(); - KURL baseURL = completeURL(baseURLString); - - Widget* widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); - if (widget) - m_containsPlugIns = true; - - return widget; -} - -void FrameLoader::didChangeTitle(DocumentLoader* loader) -{ - m_client->didChangeTitle(loader); - - // The title doesn't get communicated to the WebView until we are committed. - if (loader->isCommitted()) { - // Must update the entries in the back-forward list too. - if (m_currentHistoryItem) - m_currentHistoryItem->setTitle(loader->title()); - // This must go through the WebFrame because it has the right notion of the current b/f item. - m_client->setTitle(loader->title(), loader->urlForHistory()); - m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument - m_client->dispatchDidReceiveTitle(loader->title()); - } -} - -void FrameLoader::continueLoadWithData(SharedBuffer* buffer, const String& mimeType, const String& textEncoding, const KURL& url) -{ - m_responseMIMEType = mimeType; - didOpenURL(url); - - String encoding; - if (m_frame) - encoding = documentLoader()->overrideEncoding(); - bool userChosen = !encoding.isNull(); - if (encoding.isNull()) - encoding = textEncoding; - setEncoding(encoding, userChosen); - - ASSERT(m_frame->document()); - - addData(buffer->data(), buffer->size()); -} - -void FrameLoader::registerURLSchemeAsLocal(const String& scheme) -{ - localSchemes().add(scheme); -} - -bool FrameLoader::shouldTreatURLAsLocal(const String& url) -{ - // This avoids an allocation of another String and the HashSet contains() - // call for the file: and http: schemes. - if (url.length() >= 5) { - const UChar* s = url.characters(); - if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p' && s[4] == ':') - return false; - if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e' && s[4] == ':') - return true; - } - - int loc = url.find(':'); - if (loc == -1) - return false; - - String scheme = url.left(loc); - return localSchemes().contains(scheme); -} - -bool FrameLoader::shouldTreatSchemeAsLocal(const String& scheme) -{ - // This avoids an allocation of another String and the HashSet contains() - // call for the file: and http: schemes. - if (scheme.length() == 4) { - const UChar* s = scheme.characters(); - if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p') - return false; - if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e') - return true; - } - - if (scheme.isEmpty()) - return false; - - return localSchemes().contains(scheme); -} - -void FrameLoader::dispatchDidCommitLoad() -{ - if (m_creatingInitialEmptyDocument) - return; - -#ifndef NDEBUG - m_didDispatchDidCommitLoad = true; -#endif - - m_client->dispatchDidCommitLoad(); - - if (Page* page = m_frame->page()) - page->inspectorController()->didCommitLoad(m_documentLoader.get()); -} - -void FrameLoader::dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) -{ - m_client->assignIdentifierToInitialRequest(identifier, loader, request); - - if (Page* page = m_frame->page()) - page->inspectorController()->identifierForInitialRequest(identifier, loader, request); -} - -void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - m_client->dispatchWillSendRequest(loader, identifier, request, redirectResponse); - - if (Page* page = m_frame->page()) - page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse); -} - -void FrameLoader::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r) -{ - m_client->dispatchDidReceiveResponse(loader, identifier, r); - - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveResponse(loader, identifier, r); -} - -void FrameLoader::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) -{ - m_client->dispatchDidReceiveContentLength(loader, identifier, length); - - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveContentLength(loader, identifier, length); -} - -void FrameLoader::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) -{ - m_client->dispatchDidFinishLoading(loader, identifier); - - if (Page* page = m_frame->page()) - page->inspectorController()->didFinishLoading(loader, identifier); -} - -#if USE(LOW_BANDWIDTH_DISPLAY) - -bool FrameLoader::addLowBandwidthDisplayRequest(CachedResource* cache) -{ - if (m_frame->document()->inLowBandwidthDisplay() == false) - return false; - - // if cache is loaded, don't add to the list, where notifyFinished() is expected. - if (cache->isLoaded()) - return false; - - switch (cache->type()) { - case CachedResource::CSSStyleSheet: - case CachedResource::Script: - m_needToSwitchOutLowBandwidthDisplay = true; - m_externalRequestsInLowBandwidthDisplay.add(cache); - cache->addClient(this); - return true; - case CachedResource::ImageResource: - case CachedResource::FontResource: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif -#if ENABLE(XBL) - case CachedResource::XBLStyleSheet: -#endif - return false; - } - - ASSERT_NOT_REACHED(); - return false; -} - -void FrameLoader::removeAllLowBandwidthDisplayRequests() -{ - HashSet<CachedResource*>::iterator end = m_externalRequestsInLowBandwidthDisplay.end(); - for (HashSet<CachedResource*>::iterator it = m_externalRequestsInLowBandwidthDisplay.begin(); it != end; ++it) - (*it)->removeClient(this); - m_externalRequestsInLowBandwidthDisplay.clear(); -} - -void FrameLoader::notifyFinished(CachedResource* script) -{ - HashSet<CachedResource*>::iterator it = m_externalRequestsInLowBandwidthDisplay.find(script); - if (it != m_externalRequestsInLowBandwidthDisplay.end()) { - (*it)->removeClient(this); - m_externalRequestsInLowBandwidthDisplay.remove(it); - switchOutLowBandwidthDisplayIfReady(); - } -} - -void FrameLoader::switchOutLowBandwidthDisplayIfReady() -{ - RefPtr<Document> oldDoc = m_frame->document(); - if (oldDoc->inLowBandwidthDisplay()) { - if (!m_needToSwitchOutLowBandwidthDisplay) { - // no need to switch, just reset state - oldDoc->setLowBandwidthDisplay(false); - removeAllLowBandwidthDisplayRequests(); - m_pendingSourceInLowBandwidthDisplay = String(); - m_finishedParsingDuringLowBandwidthDisplay = false; - return; - } else if (m_externalRequestsInLowBandwidthDisplay.isEmpty() || - m_pendingSourceInLowBandwidthDisplay.length() > cMaxPendingSourceLengthInLowBandwidthDisplay) { - // clear the flag first - oldDoc->setLowBandwidthDisplay(false); - - // similar to clear(), should be refactored to share more code - oldDoc->cancelParsing(); - oldDoc->detach(); - if (m_frame->script()->isEnabled()) - m_frame->script()->clearWindowShell(); - if (m_frame->view()) - m_frame->view()->clear(); - - // similar to begin(), should be refactored to share more code - RefPtr<Document> newDoc = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode()); - m_frame->setDocument(newDoc); - newDoc->setURL(m_URL); - if (m_decoder) - newDoc->setDecoder(m_decoder.get()); - restoreDocumentState(); - dispatchWindowObjectAvailable(); - newDoc->implicitOpen(); - - // swap DocLoader ownership - DocLoader* docLoader = newDoc->docLoader(); - newDoc->setDocLoader(oldDoc->docLoader()); - newDoc->docLoader()->replaceDocument(newDoc.get()); - docLoader->replaceDocument(oldDoc.get()); - oldDoc->setDocLoader(docLoader); - - // drop the old doc - oldDoc = 0; - - // write decoded data to the new doc, similar to write() - if (m_pendingSourceInLowBandwidthDisplay.length()) { - // set cachePolicy to Cache to use the loaded resource - newDoc->docLoader()->setCachePolicy(CachePolicyCache); - if (m_decoder->encoding().usesVisualOrdering()) - newDoc->setVisuallyOrdered(); - newDoc->recalcStyle(Node::Force); - newDoc->tokenizer()->write(m_pendingSourceInLowBandwidthDisplay, true); - - if (m_finishedParsingDuringLowBandwidthDisplay) - newDoc->finishParsing(); - } - - // update rendering - newDoc->updateRendering(); - - // reset states - removeAllLowBandwidthDisplayRequests(); - m_pendingSourceInLowBandwidthDisplay = String(); - m_finishedParsingDuringLowBandwidthDisplay = false; - m_needToSwitchOutLowBandwidthDisplay = false; - } - } -} - -#endif - -} // namespace WebCore diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h deleted file mode 100644 index 47a56af..0000000 --- a/WebCore/loader/FrameLoader.h +++ /dev/null @@ -1,701 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FrameLoader_h -#define FrameLoader_h - -#include "CachedResource.h" -#include "CachePolicy.h" -#include "FormState.h" -#include "FrameLoaderTypes.h" -#include "KURL.h" -#include "StringHash.h" -#include "Timer.h" -#include <wtf/Forward.h> -#include <wtf/HashSet.h> -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> -#include <wtf/RefPtr.h> -#include "ResourceRequest.h" -#if USE(LOW_BANDWIDTH_DISPLAY) -#include "CachedResourceClient.h" -#endif - -namespace WebCore { - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - class Archive; - class ArchiveResource; -#endif - class AuthenticationChallenge; - class CachedPage; - class Document; - class DocumentLoader; - class Element; - class Event; - class FormData; - class Frame; - class FrameLoaderClient; - class HistoryItem; - class HTMLFormElement; - class HTMLFrameOwnerElement; - class IconLoader; - class IntSize; - class NavigationAction; - class Node; - class Page; - class RenderPart; - class ResourceError; - class ResourceLoader; - class ResourceRequest; - class ResourceResponse; - class SecurityOrigin; - class SharedBuffer; - class SubstituteData; - class TextResourceDecoder; - class Widget; - - struct FormSubmission; - struct FrameLoadRequest; - struct ScheduledRedirection; - struct WindowFeatures; - - bool isBackForwardLoadType(FrameLoadType); - - typedef void (*NavigationPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - typedef void (*NewWindowPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction); - - class PolicyCheck { - public: - PolicyCheck(); - - void clear(); - void set(const ResourceRequest&, PassRefPtr<FormState>, - NavigationPolicyDecisionFunction, void* argument); - void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, - NewWindowPolicyDecisionFunction, void* argument); - void set(ContentPolicyDecisionFunction, void* argument); - - const ResourceRequest& request() const { return m_request; } - void clearRequest(); - - void call(bool shouldContinue); - void call(PolicyAction); - void cancel(); - - private: - ResourceRequest m_request; - RefPtr<FormState> m_formState; - String m_frameName; - - NavigationPolicyDecisionFunction m_navigationFunction; - NewWindowPolicyDecisionFunction m_newWindowFunction; - ContentPolicyDecisionFunction m_contentFunction; - void* m_argument; - }; - - class FrameLoader : Noncopyable -#if USE(LOW_BANDWIDTH_DISPLAY) - , private CachedResourceClient -#endif - { - public: - FrameLoader(Frame*, FrameLoaderClient*); - ~FrameLoader(); - - void init(); - - Frame* frame() const { return m_frame; } - - // FIXME: This is not cool, people. We should aim to consolidate these variety of loading related methods into a smaller set, - // and try to reuse more of the same logic by extracting common code paths. - void prepareForLoadStart(); - void setupForReplace(); - void setupForReplaceByMIMEType(const String& newMIMEType); - - void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy - void load(DocumentLoader*); // Calls loadWithDocumentLoader - - void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, // Calls loadWithDocumentLoader() - FrameLoadType, PassRefPtr<FormState>); - -#ifdef ANDROID_USER_GESTURE - void loadPostRequest(const ResourceRequest& inRequest, const String& referrer, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction - const String& frameName, Event* event, PassRefPtr<FormState> prpFormState, bool userGesture); - - void loadURL(const KURL& newURL, const String& referrer, const String& frameName, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction or else dispatches to navigation policy delegate - FrameLoadType, Event* event, PassRefPtr<FormState> prpFormState, bool userGesture); -#else - void loadPostRequest(const ResourceRequest& inRequest, const String& referrer, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction - const String& frameName, Event* event, PassRefPtr<FormState> prpFormState); - - void loadURL(const KURL& newURL, const String& referrer, const String& frameName, // Called by loadFrameRequestWithFormAndValues(), calls loadWithNavigationAction or else dispatches to navigation policy delegate - FrameLoadType, Event* event, PassRefPtr<FormState> prpFormState); -#endif - void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*); - - void loadFrameRequestWithFormState(const FrameLoadRequest&, bool lockHistory, Event*, PassRefPtr<FormState>); - void loadFrameRequestWithFormAndValues(const FrameLoadRequest&, bool lockHistory, // Called by submitForm, calls loadPostRequest() - Event*, HTMLFormElement*, const HashMap<String, String>& formValues); - - void load(const ResourceRequest&); // Called by WebFrame, calls (ResourceRequest, SubstituteData) - void load(const ResourceRequest&, const SubstituteData&); // Called both by WebFrame and internally, calls (DocumentLoader*) - void load(const ResourceRequest&, const String& frameName); // Called by WebPluginController - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - void loadArchive(PassRefPtr<Archive> archive); -#endif - - // Returns true for any non-local URL. If Document parameter is supplied, its local load policy dictates, - // otherwise if referrer is non-empty and represents a local file, then the local load is allowed. - static bool canLoad(const KURL&, const String& referrer, const Document* theDocument = 0); - static void reportLocalLoadFailed(Frame*, const String& url); - - static bool shouldHideReferrer(const KURL& url, const String& referrer); - - // Called by createWindow in JSDOMWindowBase.cpp, e.g. to fulfill a modal dialog creation - Frame* createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest&, const WindowFeatures&, bool& created); - - unsigned long loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data); - - bool canHandleRequest(const ResourceRequest&); - - // Also not cool. - void stopAllLoaders(); - void stopForUserCancel(bool deferCheckLoadComplete = false); - - bool isLoadingMainResource() const { return m_isLoadingMainResource; } - bool isLoading() const; - bool frameHasLoaded() const; - - int numPendingOrLoadingRequests(bool recurse) const; - bool isReloading() const; - String referrer() const; - String outgoingReferrer() const; - String outgoingOrigin() const; - void loadEmptyDocumentSynchronously(); - - DocumentLoader* activeDocumentLoader() const; - DocumentLoader* documentLoader() const; - DocumentLoader* policyDocumentLoader() const; - DocumentLoader* provisionalDocumentLoader() const; - FrameState state() const; - static double timeOfLastCompletedLoad(); - - void didReceiveAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - void didCancelAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - - void assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest&); - void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); - void didReceiveResponse(ResourceLoader*, const ResourceResponse&); - void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived); - void didFinishLoad(ResourceLoader*); - void didFailToLoad(ResourceLoader*, const ResourceError&); - const ResourceRequest& originalRequest() const; - const ResourceRequest& initialRequest() const; - void receivedMainResourceError(const ResourceError&, bool isComplete); - void receivedData(const char*, int); - - void handleFallbackContent(); - bool isStopping() const; - - void finishedLoading(); - - ResourceError cancelledError(const ResourceRequest&) const; - ResourceError fileDoesNotExistError(const ResourceResponse&) const; - ResourceError blockedError(const ResourceRequest&) const; - ResourceError cannotShowURLError(const ResourceRequest&) const; - - void cannotShowMIMEType(const ResourceResponse&); - ResourceError interruptionForPolicyChangeError(const ResourceRequest&); - - bool isHostedByObjectElement() const; - bool isLoadingMainFrame() const; - bool canShowMIMEType(const String& MIMEType) const; - bool representationExistsForURLScheme(const String& URLScheme); - String generatedMIMETypeForURLScheme(const String& URLScheme); - - void notifyIconChanged(); - - void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction function, void* argument); - void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument); - void cancelContentPolicyCheck(); - - void reload(); - void reloadAllowingStaleData(const String& overrideEncoding); - - void didReceiveServerRedirectForProvisionalLoadForFrame(); - void finishedLoadingDocument(DocumentLoader*); - void committedLoad(DocumentLoader*, const char*, int); - bool isReplacing() const; - void setReplacing(); - void revertToProvisional(DocumentLoader*); - void setMainDocumentError(DocumentLoader*, const ResourceError&); - void mainReceivedCompleteError(DocumentLoader*, const ResourceError&); - bool subframeIsLoading() const; - void willChangeTitle(DocumentLoader*); - void didChangeTitle(DocumentLoader*); - - FrameLoadType loadType() const; - - void didFirstLayout(); - bool firstLayoutDone() const; - - void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress); - void clientRedirected(const KURL&, double delay, double fireDate, bool lockHistory, bool isJavaScriptFormAction); - bool shouldReload(const KURL& currentURL, const KURL& destinationURL); - - bool isQuickRedirectComing() const; - - void sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse&, int length, const ResourceError&); - void requestFromDelegate(ResourceRequest&, unsigned long& identifier, ResourceError&); - void loadedResourceFromMemoryCache(const CachedResource*); - - void recursiveCheckLoadComplete(); - void checkLoadComplete(); - void detachFromParent(); - void detachChildren(); - - void addExtraFieldsToRequest(ResourceRequest&, bool isMainResource, bool alwaysFromRequest); - static void addHTTPOriginIfNeeded(ResourceRequest&, String origin); - - FrameLoaderClient* client() const; - - void setDefersLoading(bool); - - void changeLocation(const String& url, const String& referrer, bool lockHistory = true, bool userGesture = false); - void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool userGesture = false); - void urlSelected(const ResourceRequest&, const String& target, Event*, bool lockHistory, bool userGesture); - void urlSelected(const FrameLoadRequest&, Event*, bool lockHistory); - - bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName); - Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); - - void submitForm(const char* action, const String& url, PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary, Event*); - void submitFormAgain(); - void submitForm(const FrameLoadRequest&, Event*); - - void stop(); - void stopLoading(bool sendUnload); - bool closeURL(); - - void didExplicitOpen(); - - KURL iconURL(); - void commitIconURLToIconDatabase(const KURL&); - - KURL baseURL() const; - String baseTarget() const; - KURL dataURLBaseFromRequest(const ResourceRequest& request) const; - - bool isScheduledLocationChangePending() const { return m_scheduledRedirection && isLocationChange(*m_scheduledRedirection); } - void scheduleHTTPRedirection(double delay, const String& url); - void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool userGesture = false); - void scheduleRefresh(bool userGesture = false); - void scheduleHistoryNavigation(int steps); - - bool canGoBackOrForward(int distance) const; - void goBackOrForward(int distance); - int getHistoryLength(); - KURL historyURL(int distance); - - void begin(); - void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0); - - void write(const char* str, int len = -1, bool flush = false); - void write(const String&); - void end(); - void endIfNotLoadingMainResource(); - - void setEncoding(const String& encoding, bool userChosen); - String encoding() const; - - // Returns true if url is a JavaScript URL. - bool executeIfJavaScriptURL(const KURL& url, bool userGesture = false, bool replaceDocument = true); - - JSC::JSValue* executeScript(const String& url, int baseLine, const String& script); - JSC::JSValue* executeScript(const String& script, bool forceUserGesture = false); - - void gotoAnchor(); - bool gotoAnchor(const String& name); // returns true if the anchor was found - void scrollToAnchor(const KURL&); - - void tokenizerProcessedData(); - - void handledOnloadEvents(); - String userAgent(const KURL&) const; - - Widget* createJavaAppletWidget(const IntSize&, Element*, const HashMap<String, String>& args); - - void dispatchWindowObjectAvailable(); - void restoreDocumentState(); - - Frame* opener(); - void setOpener(Frame*); - bool openedByDOM() const; - void setOpenedByDOM(); - - void provisionalLoadStarted(); - - bool userGestureHint(); - - void resetMultipleFormSubmissionProtection(); - void didNotOpenURL(const KURL&); - - void addData(const char* bytes, int length); - - bool canCachePage(); - - void checkCallImplicitClose(); - bool didOpenURL(const KURL&); - - void frameDetached(); - - const KURL& url() const { return m_URL; } - - void updateBaseURLForEmptyDocument(); - - void setResponseMIMEType(const String&); - const String& responseMIMEType() const; - - bool containsPlugins() const; - - void loadDone(); - void finishedParsing(); - void checkCompleted(); - void scheduleCheckCompleted(); - void scheduleCheckLoadComplete(); - - void clearRecordedFormValues(); - void setFormAboutToBeSubmitted(PassRefPtr<HTMLFormElement> element); - void recordFormValue(const String& name, const String& value); - - bool isComplete() const; - - bool requestObject(RenderPart* frame, const String& url, const AtomicString& frameName, - const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); - - KURL completeURL(const String& url); - - void didTellClientAboutLoad(const String& url); - bool haveToldClientAboutLoad(const String& url); - - KURL originalRequestURL() const; - - void cancelAndClear(); - - void setTitle(const String&); - - bool shouldTreatURLAsSameAsCurrent(const KURL&) const; - - void commitProvisionalLoad(PassRefPtr<CachedPage>); - - void goToItem(HistoryItem*, FrameLoadType); - void saveDocumentAndScrollState(); - void saveScrollPositionAndViewStateToItem(HistoryItem*); - - // FIXME: These accessors are here for a dwindling number of users in WebKit, WebFrame - // being the primary one. After they're no longer needed there, they can be removed! - HistoryItem* currentHistoryItem(); - HistoryItem* previousHistoryItem(); - HistoryItem* provisionalHistoryItem(); - void setCurrentHistoryItem(PassRefPtr<HistoryItem>); - void setPreviousHistoryItem(PassRefPtr<HistoryItem>); - void setProvisionalHistoryItem(PassRefPtr<HistoryItem>); - - void continueLoadWithData(SharedBuffer*, const String& mimeType, const String& textEncoding, const KURL&); - - enum LocalLoadPolicy { - AllowLocalLoadsForAll, // No restriction on local loads. - AllowLocalLoadsForLocalAndSubstituteData, - AllowLocalLoadsForLocalOnly, - }; - static void setLocalLoadPolicy(LocalLoadPolicy); - static bool restrictAccessToLocal(); - static bool allowSubstituteDataAccessToLocal(); - - static void registerURLSchemeAsLocal(const String& scheme); - static bool shouldTreatURLAsLocal(const String&); - static bool shouldTreatSchemeAsLocal(const String&); - -#if USE(LOW_BANDWIDTH_DISPLAY) - bool addLowBandwidthDisplayRequest(CachedResource*); - void needToSwitchOutLowBandwidthDisplay() { m_needToSwitchOutLowBandwidthDisplay = true; } - - // Client can control whether to use low bandwidth display on a per frame basis. - // However, this should only be used for the top frame, not sub-frame. - void setUseLowBandwidthDisplay(bool lowBandwidth) { m_useLowBandwidthDisplay = lowBandwidth; } - bool useLowBandwidthDisplay() const { return m_useLowBandwidthDisplay; } -#endif - - bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; } - - void iconLoadDecisionAvailable(); - - bool shouldAllowNavigation(Frame* targetFrame) const; - Frame* findFrameForNavigation(const AtomicString& name); - - void startIconLoader(); - - void applyUserAgent(ResourceRequest& request); - - private: - PassRefPtr<HistoryItem> createHistoryItem(bool useOriginal); - PassRefPtr<HistoryItem> createHistoryItemTree(Frame* targetFrame, bool clipAtTarget); - - void addBackForwardItemClippedAtTarget(bool doClip); - void restoreScrollPositionAndViewState(); - void saveDocumentState(); - void loadItem(HistoryItem*, FrameLoadType); - bool urlsMatchItem(HistoryItem*) const; - void invalidateCurrentItemCachedPage(); - void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType); - bool childFramesMatchItem(HistoryItem*) const; - - void updateHistoryForBackForwardNavigation(); - void updateHistoryForReload(); - void updateHistoryForStandardLoad(); - void updateHistoryForRedirectWithLockedHistory(); - void updateHistoryForClientRedirect(); - void updateHistoryForCommit(); - void updateHistoryForAnchorScroll(); - - void redirectionTimerFired(Timer<FrameLoader>*); - void checkCompletedTimerFired(Timer<FrameLoader>*); - void checkLoadCompleteTimerFired(Timer<FrameLoader>*); - - void cancelRedirection(bool newLoadInProgress = false); - - void started(); - - void completed(); - void parentCompleted(); - - bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); - bool loadPlugin(RenderPart*, const KURL&, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); - - bool loadProvisionalItemFromCachedPage(); - void cachePageForHistoryItem(HistoryItem*); - - void receivedFirstData(); - - void updatePolicyBaseURL(); - void setPolicyBaseURL(const KURL&); - - // Also not cool. - void stopLoadingSubframes(); - - void clearProvisionalLoad(); - void markLoadComplete(); - void transitionToCommitted(PassRefPtr<CachedPage>); - void frameLoadCompleted(); - - void mainReceivedError(const ResourceError&, bool isComplete); - - void setLoadType(FrameLoadType); - - void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, - NavigationPolicyDecisionFunction, void* argument); - void checkNewWindowPolicy(const NavigationAction&, const ResourceRequest&, - PassRefPtr<FormState>, const String& frameName); - - void continueAfterNavigationPolicy(PolicyAction); - void continueAfterNewWindowPolicy(PolicyAction); - void continueAfterContentPolicy(PolicyAction); - void continueLoadAfterWillSubmitForm(PolicyAction = PolicyUse); - - static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); - bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url); - void addHistoryItemForFragmentScroll(); - - void stopPolicyCheck(); - - void closeDocument(); - - void checkLoadCompleteForThisFrame(); - - void setDocumentLoader(DocumentLoader*); - void setPolicyDocumentLoader(DocumentLoader*); - void setProvisionalDocumentLoader(DocumentLoader*); - - void setState(FrameState); - - void closeOldDataSources(); - void open(CachedPage&); - void opened(); - void updateHistoryAfterClientRedirect(); - - void clear(bool clearWindowProperties = true, bool clearScriptObjects = true); - - bool shouldReloadToHandleUnreachableURL(DocumentLoader*); - void handleUnimplementablePolicy(const ResourceError&); - - void scheduleRedirection(ScheduledRedirection*); - void startRedirectionTimer(); - void stopRedirectionTimer(); - -#if USE(LOW_BANDWIDTH_DISPLAY) - // implementation of CachedResourceClient - virtual void notifyFinished(CachedResource*); - - void removeAllLowBandwidthDisplayRequests(); - void switchOutLowBandwidthDisplayIfReady(); -#endif - - void dispatchDidCommitLoad(); - void dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); - void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); - void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); - void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length); - void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); - - static bool isLocationChange(const ScheduledRedirection&); - - Frame* m_frame; - FrameLoaderClient* m_client; - - FrameState m_state; - FrameLoadType m_loadType; - - // Document loaders for the three phases of frame loading. Note that while - // a new request is being loaded, the old document loader may still be referenced. - // E.g. while a new request is in the "policy" state, the old document loader may - // be consulted in particular as it makes sense to imply certain settings on the new loader. - RefPtr<DocumentLoader> m_documentLoader; - RefPtr<DocumentLoader> m_provisionalDocumentLoader; - RefPtr<DocumentLoader> m_policyDocumentLoader; - - // This identifies the type of navigation action which prompted this load. Note - // that WebKit conveys this value as the WebActionNavigationTypeKey value - // on navigation action delegate callbacks. - FrameLoadType m_policyLoadType; - PolicyCheck m_policyCheck; - - bool m_delegateIsHandlingProvisionalLoadError; - bool m_delegateIsDecidingNavigationPolicy; - bool m_delegateIsHandlingUnimplementablePolicy; - - bool m_firstLayoutDone; - bool m_quickRedirectComing; - bool m_sentRedirectNotification; - bool m_inStopAllLoaders; - bool m_navigationDuringLoad; - - String m_outgoingReferrer; - - CachePolicy m_cachePolicy; - - HashSet<String> m_urlsClientKnowsAbout; - - OwnPtr<FormSubmission> m_deferredFormSubmission; - - bool m_isExecutingJavaScriptFormAction; - bool m_isRunningScript; - - String m_responseMIMEType; - - bool m_didCallImplicitClose; - bool m_wasUnloadEventEmitted; - bool m_isComplete; - bool m_isLoadingMainResource; - - KURL m_URL; - KURL m_workingURL; - - OwnPtr<IconLoader> m_iconLoader; - bool m_mayLoadIconLater; - - bool m_cancellingWithLoadInProgress; - - OwnPtr<ScheduledRedirection> m_scheduledRedirection; - - bool m_needsClear; - bool m_receivedData; - - bool m_encodingWasChosenByUser; - String m_encoding; - RefPtr<TextResourceDecoder> m_decoder; - - bool m_containsPlugIns; - - RefPtr<HTMLFormElement> m_formAboutToBeSubmitted; - HashMap<String, String> m_formValuesAboutToBeSubmitted; - KURL m_submittedFormURL; - - Timer<FrameLoader> m_redirectionTimer; - Timer<FrameLoader> m_checkCompletedTimer; - Timer<FrameLoader> m_checkLoadCompleteTimer; - - Frame* m_opener; - HashSet<Frame*> m_openedFrames; - - bool m_openedByDOM; - - bool m_creatingInitialEmptyDocument; - bool m_isDisplayingInitialEmptyDocument; - bool m_committedFirstRealDocumentLoad; - - RefPtr<HistoryItem> m_currentHistoryItem; - RefPtr<HistoryItem> m_previousHistoryItem; - RefPtr<HistoryItem> m_provisionalHistoryItem; - - bool m_didPerformFirstNavigation; - -#ifndef NDEBUG - bool m_didDispatchDidCommitLoad; -#endif - -#if USE(LOW_BANDWIDTH_DISPLAY) - // whether to use low bandwidth dislay, set by client - bool m_useLowBandwidthDisplay; - - // whether to call finishParsing() in switchOutLowBandwidthDisplayIfReady() - bool m_finishedParsingDuringLowBandwidthDisplay; - - // whether to call switchOutLowBandwidthDisplayIfReady; - // true if there is external css, javascript, or subframe/plugin - bool m_needToSwitchOutLowBandwidthDisplay; - - String m_pendingSourceInLowBandwidthDisplay; - HashSet<CachedResource*> m_externalRequestsInLowBandwidthDisplay; -#endif - }; - -} - -#endif diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h deleted file mode 100644 index 6e2aba9..0000000 --- a/WebCore/loader/FrameLoaderClient.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FrameLoaderClient_h -#define FrameLoaderClient_h - -#include "FrameLoaderTypes.h" -#include <wtf/Forward.h> -#include <wtf/Platform.h> -#include <wtf/Vector.h> - -typedef class _jobject* jobject; - -#if PLATFORM(MAC) && !defined(__OBJC__) -class NSCachedURLResponse; -class NSView; -#endif - -namespace WebCore { - - class AuthenticationChallenge; - class CachedPage; - class DocumentLoader; - class Element; - class FormState; - class Frame; - class FrameLoader; - class HistoryItem; - class HTMLFrameOwnerElement; - class IntSize; - class KURL; - class NavigationAction; - class ResourceError; - class ResourceHandle; - class ResourceLoader; - class ResourceResponse; - class SharedBuffer; - class SubstituteData; - class String; - class Widget; - - class ResourceRequest; - -#ifdef ANDROID_HISTORY_CLIENT - class BackForwardList; -#endif - - typedef void (FrameLoader::*FramePolicyFunction)(PolicyAction); - - class FrameLoaderClient { - public: - virtual ~FrameLoaderClient() { } - virtual void frameLoaderDestroyed() = 0; - - virtual bool hasWebView() const = 0; // mainly for assertions - - virtual bool hasHTMLView() const { return true; } - - virtual void makeRepresentation(DocumentLoader*) = 0; - virtual void forceLayout() = 0; - virtual void forceLayoutForNonHTML() = 0; - - virtual void setCopiesOnScroll() = 0; - - virtual void detachedFromParent2() = 0; - virtual void detachedFromParent3() = 0; - - virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&) = 0; - - virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse) = 0; - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; - virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&) = 0; - virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived) = 0; - virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) = 0; - virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&) = 0; - virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) = 0; - - virtual void dispatchDidHandleOnloadEvents() = 0; - virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() = 0; - virtual void dispatchDidCancelClientRedirect() = 0; - virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate) = 0; - virtual void dispatchDidChangeLocationWithinPage() = 0; - virtual void dispatchWillClose() = 0; - virtual void dispatchDidReceiveIcon() = 0; - virtual void dispatchDidStartProvisionalLoad() = 0; - virtual void dispatchDidReceiveTitle(const String& title) = 0; - virtual void dispatchDidCommitLoad() = 0; - virtual void dispatchDidFailProvisionalLoad(const ResourceError&) = 0; - virtual void dispatchDidFailLoad(const ResourceError&) = 0; - virtual void dispatchDidFinishDocumentLoad() = 0; - virtual void dispatchDidFinishLoad() = 0; - virtual void dispatchDidFirstLayout() = 0; - - virtual Frame* dispatchCreatePage() = 0; - virtual void dispatchShow() = 0; - - virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&) = 0; - virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName) = 0; - virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>) = 0; - virtual void cancelPolicyCheck() = 0; - - virtual void dispatchUnableToImplementPolicy(const ResourceError&) = 0; - - virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>) = 0; - - virtual void dispatchDidLoadMainResource(DocumentLoader*) = 0; - virtual void revertToProvisionalState(DocumentLoader*) = 0; - virtual void setMainDocumentError(DocumentLoader*, const ResourceError&) = 0; - - // Maybe these should go into a ProgressTrackerClient some day - virtual void willChangeEstimatedProgress() { } - virtual void didChangeEstimatedProgress() { } - virtual void postProgressStartedNotification() = 0; - virtual void postProgressEstimateChangedNotification() = 0; - virtual void postProgressFinishedNotification() = 0; - - virtual void setMainFrameDocumentReady(bool) = 0; - - virtual void startDownload(const ResourceRequest&) = 0; - - virtual void willChangeTitle(DocumentLoader*) = 0; - virtual void didChangeTitle(DocumentLoader*) = 0; - - virtual void committedLoad(DocumentLoader*, const char*, int) = 0; - virtual void finishedLoading(DocumentLoader*) = 0; - - virtual void updateGlobalHistory(const KURL&) = 0; - virtual bool shouldGoToHistoryItem(HistoryItem*) const = 0; -#ifdef ANDROID_HISTORY_CLIENT - virtual void dispatchDidAddHistoryItem(HistoryItem*) const = 0; - virtual void dispatchDidRemoveHistoryItem(HistoryItem*, int) const = 0; - virtual void dispatchDidChangeHistoryIndex(BackForwardList*) const = 0; -#endif - - virtual ResourceError cancelledError(const ResourceRequest&) = 0; - virtual ResourceError blockedError(const ResourceRequest&) = 0; - virtual ResourceError cannotShowURLError(const ResourceRequest&) = 0; - virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) = 0; - - virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) = 0; - virtual ResourceError fileDoesNotExistError(const ResourceResponse&) = 0; - virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) = 0; - - virtual bool shouldFallBack(const ResourceError&) = 0; - - virtual bool canHandleRequest(const ResourceRequest&) const = 0; - virtual bool canShowMIMEType(const String& MIMEType) const = 0; - virtual bool representationExistsForURLScheme(const String& URLScheme) const = 0; - virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const = 0; - - virtual void frameLoadCompleted() = 0; - virtual void saveViewStateToItem(HistoryItem*) = 0; - virtual void restoreViewState() = 0; - virtual void provisionalLoadStarted() = 0; - virtual void didFinishLoad() = 0; - virtual void prepareForDataSourceReplacement() = 0; - - virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest&, const SubstituteData&) = 0; - virtual void setTitle(const String& title, const KURL&) = 0; - - virtual String userAgent(const KURL&) = 0; - - virtual void savePlatformDataToCachedPage(CachedPage*) = 0; - virtual void transitionToCommittedFromCachedPage(CachedPage*) = 0; - virtual void transitionToCommittedForNewPage() = 0; - - virtual bool canCachePage() const = 0; - virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) = 0; - - virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, - const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) = 0; - virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0; - virtual void redirectDataToPlugin(Widget* pluginWidget) = 0; - - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) = 0; - - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) = 0; - virtual String overrideMediaType() const = 0; - - virtual void windowObjectCleared() = 0; - virtual void didPerformFirstNavigation() const = 0; // "Navigation" here means a transition from one page to another that ends up in the back/forward list. - - virtual void registerForIconNotification(bool listen = true) = 0; - -#if PLATFORM(MAC) -#if ENABLE(MAC_JAVA_BRIDGE) - virtual jobject javaApplet(NSView*) { return 0; } -#endif - virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const = 0; -#endif - }; - -} // namespace WebCore - -#endif // FrameLoaderClient_h diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h deleted file mode 100644 index 86d8a5b..0000000 --- a/WebCore/loader/FrameLoaderTypes.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FrameLoaderTypes_h -#define FrameLoaderTypes_h - -namespace WebCore { - - enum FrameState { - FrameStateProvisional, - // This state indicates we are ready to commit to a page, - // which means the view will transition to use the new data source. - FrameStateCommittedPage, - FrameStateComplete - }; - - enum PolicyAction { - PolicyUse, - PolicyDownload, - PolicyIgnore, - }; - - enum FrameLoadType { - FrameLoadTypeStandard, - FrameLoadTypeBack, - FrameLoadTypeForward, - FrameLoadTypeIndexedBackForward, // a multi-item hop in the backforward list - FrameLoadTypeReload, - FrameLoadTypeReloadAllowingStaleData, - FrameLoadTypeSame, // user loads same URL again (but not reload button) - FrameLoadTypeRedirectWithLockedHistory, - FrameLoadTypeReplace - }; - - enum NavigationType { - NavigationTypeLinkClicked, - NavigationTypeFormSubmitted, - NavigationTypeBackForward, - NavigationTypeReload, - NavigationTypeFormResubmitted, - NavigationTypeOther - }; - - enum ObjectContentType { - ObjectContentNone, - ObjectContentImage, - ObjectContentFrame, - ObjectContentNetscapePlugin, - ObjectContentOtherPlugin - }; -} - -#endif diff --git a/WebCore/loader/ImageDocument.cpp b/WebCore/loader/ImageDocument.cpp deleted file mode 100644 index 39b1db6..0000000 --- a/WebCore/loader/ImageDocument.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ImageDocument.h" - -#include "CachedImage.h" -#include "DocumentLoader.h" -#include "Element.h" -#include "EventListener.h" -#include "EventNames.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameView.h" -#include "HTMLImageElement.h" -#include "HTMLNames.h" -#include "LocalizedStrings.h" -#include "MouseEvent.h" -#include "Page.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "Text.h" -#include "XMLTokenizer.h" - -using std::min; - -namespace WebCore { - -using namespace HTMLNames; - -class ImageEventListener : public EventListener { -public: - static PassRefPtr<ImageEventListener> create(ImageDocument* document) { return adoptRef(new ImageEventListener(document)); } - virtual void handleEvent(Event*, bool isWindowEvent); - -private: - ImageEventListener(ImageDocument* document) : m_doc(document) { } - ImageDocument* m_doc; -}; - -class ImageTokenizer : public Tokenizer { -public: - ImageTokenizer(ImageDocument* doc) : m_doc(doc) {} - - virtual bool write(const SegmentedString&, bool appendData); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } - virtual bool writeRawData(const char* data, int len); - -private: - ImageDocument* m_doc; -}; - -class ImageDocumentElement : public HTMLImageElement { -public: - ImageDocumentElement(ImageDocument* doc) : HTMLImageElement(doc), m_imageDocument(doc) { } - virtual ~ImageDocumentElement(); - virtual void willMoveToNewOwnerDocument(); - -private: - ImageDocument* m_imageDocument; -}; - -// -------- - -bool ImageTokenizer::write(const SegmentedString& s, bool appendData) -{ - ASSERT_NOT_REACHED(); - return false; -} - -bool ImageTokenizer::writeRawData(const char* data, int len) -{ - CachedImage* cachedImage = m_doc->cachedImage(); - cachedImage->data(m_doc->frame()->loader()->documentLoader()->mainResourceData(), false); - - m_doc->imageChanged(); - - return false; -} - -void ImageTokenizer::finish() -{ - if (!m_parserStopped && m_doc->imageElement()) { - CachedImage* cachedImage = m_doc->cachedImage(); - RefPtr<SharedBuffer> data = m_doc->frame()->loader()->documentLoader()->mainResourceData(); - - // If this is a multipart image, make a copy of the current part, since the resource data - // will be overwritten by the next part. - if (m_doc->frame()->loader()->documentLoader()->isLoadingMultipartContent()) - data = data->copy(); - - cachedImage->data(data.release(), true); - cachedImage->finish(); - - cachedImage->setResponse(m_doc->frame()->loader()->documentLoader()->response()); - - IntSize size = cachedImage->imageSize(m_doc->frame()->pageZoomFactor()); - if (size.width()) { - // Compute the title, we use the filename of the resource, falling - // back on the hostname if there is no path. - String fileName = m_doc->url().lastPathComponent(); - if (fileName.isEmpty()) - fileName = m_doc->url().host(); - m_doc->setTitle(imageTitle(fileName, size)); - } - - m_doc->imageChanged(); - } - - m_doc->finishedParsing(); -} - -bool ImageTokenizer::isWaitingForScripts() const -{ - // An image document is never waiting for scripts - return false; -} - -// -------- - -ImageDocument::ImageDocument(Frame* frame) - : HTMLDocument(frame) - , m_imageElement(0) - , m_imageSizeIsKnown(false) - , m_didShrinkImage(false) - , m_shouldShrinkImage(shouldShrinkToFit()) -{ - setParseMode(Compat); -} - -Tokenizer* ImageDocument::createTokenizer() -{ - return new ImageTokenizer(this); -} - -void ImageDocument::createDocumentStructure() -{ - ExceptionCode ec; - - RefPtr<Element> rootElement = createElementNS(xhtmlNamespaceURI, "html", ec); - appendChild(rootElement, ec); - - RefPtr<Element> body = createElementNS(xhtmlNamespaceURI, "body", ec); - body->setAttribute(styleAttr, "margin: 0px;"); - - rootElement->appendChild(body, ec); - - RefPtr<ImageDocumentElement> imageElement = new ImageDocumentElement(this); - - imageElement->setAttribute(styleAttr, "-webkit-user-select: none"); - imageElement->setLoadManually(true); - imageElement->setSrc(url().string()); - - body->appendChild(imageElement, ec); - - if (shouldShrinkToFit()) { - // Add event listeners - RefPtr<EventListener> listener = ImageEventListener::create(this); - addWindowEventListener("resize", listener, false); - imageElement->addEventListener("click", listener.release(), false); - } - - m_imageElement = imageElement.get(); -} - -float ImageDocument::scale() const -{ - if (!m_imageElement) - return 1.0f; - - IntSize imageSize = m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()); - IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height()); - - float widthScale = (float)windowSize.width() / imageSize.width(); - float heightScale = (float)windowSize.height() / imageSize.height(); - - return min(widthScale, heightScale); -} - -void ImageDocument::resizeImageToFit() -{ - if (!m_imageElement) - return; - - IntSize imageSize = m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()); - - float scale = this->scale(); - m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale)); - m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale)); - - ExceptionCode ec; - m_imageElement->style()->setProperty("cursor", "-webkit-zoom-in", ec); -} - -void ImageDocument::imageClicked(int x, int y) -{ - if (!m_imageSizeIsKnown || imageFitsInWindow()) - return; - - m_shouldShrinkImage = !m_shouldShrinkImage; - - if (m_shouldShrinkImage) - windowSizeChanged(); - else { - restoreImageSize(); - - updateLayout(); - - float scale = this->scale(); - - int scrollX = static_cast<int>(x / scale - (float)frame()->view()->width() / 2); - int scrollY = static_cast<int>(y / scale - (float)frame()->view()->height() / 2); - - frame()->view()->setScrollPosition(IntPoint(scrollX, scrollY)); - } -} - -void ImageDocument::imageChanged() -{ - ASSERT(m_imageElement); - - if (m_imageSizeIsKnown) - return; - - if (m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()).isEmpty()) - return; - - m_imageSizeIsKnown = true; - - if (shouldShrinkToFit()) { - // Force resizing of the image - windowSizeChanged(); - } -} - -void ImageDocument::restoreImageSize() -{ - if (!m_imageElement || !m_imageSizeIsKnown) - return; - - m_imageElement->setWidth(m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()).width()); - m_imageElement->setHeight(m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()).height()); - - ExceptionCode ec; - if (imageFitsInWindow()) - m_imageElement->style()->removeProperty("cursor", ec); - else - m_imageElement->style()->setProperty("cursor", "-webkit-zoom-out", ec); - - m_didShrinkImage = false; -} - -bool ImageDocument::imageFitsInWindow() const -{ - if (!m_imageElement) - return true; - - IntSize imageSize = m_imageElement->cachedImage()->imageSize(frame()->pageZoomFactor()); - IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height()); - - return imageSize.width() <= windowSize.width() && imageSize.height() <= windowSize.height(); -} - -void ImageDocument::windowSizeChanged() -{ - if (!m_imageElement || !m_imageSizeIsKnown) - return; - - bool fitsInWindow = imageFitsInWindow(); - - // If the image has been explicitly zoomed in, restore the cursor if the image fits - // and set it to a zoom out cursor if the image doesn't fit - if (!m_shouldShrinkImage) { - ExceptionCode ec; - - if (fitsInWindow) - m_imageElement->style()->removeProperty("cursor", ec); - else - m_imageElement->style()->setProperty("cursor", "-webkit-zoom-out", ec); - return; - } - - if (m_didShrinkImage) { - // If the window has been resized so that the image fits, restore the image size - // otherwise update the restored image size. - if (fitsInWindow) - restoreImageSize(); - else - resizeImageToFit(); - } else { - // If the image isn't resized but needs to be, then resize it. - if (!fitsInWindow) { - resizeImageToFit(); - m_didShrinkImage = true; - } - } -} - -CachedImage* ImageDocument::cachedImage() -{ - if (!m_imageElement) - createDocumentStructure(); - - return m_imageElement->cachedImage(); -} - -bool ImageDocument::shouldShrinkToFit() const -{ - return frame()->page()->settings()->shrinksStandaloneImagesToFit() && - frame()->page()->mainFrame() == frame(); -} - -// -------- - -void ImageEventListener::handleEvent(Event* event, bool isWindowEvent) -{ - if (event->type() == eventNames().resizeEvent) - m_doc->windowSizeChanged(); - else if (event->type() == eventNames().clickEvent) { - MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); - m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); - } -} - -// -------- - -ImageDocumentElement::~ImageDocumentElement() -{ - if (m_imageDocument) - m_imageDocument->disconnectImageElement(); -} - -void ImageDocumentElement::willMoveToNewOwnerDocument() -{ - if (m_imageDocument) { - m_imageDocument->disconnectImageElement(); - m_imageDocument = 0; - } - HTMLImageElement::willMoveToNewOwnerDocument(); -} - -} diff --git a/WebCore/loader/ImageDocument.h b/WebCore/loader/ImageDocument.h deleted file mode 100644 index 1bc5245..0000000 --- a/WebCore/loader/ImageDocument.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ImageDocument_h -#define ImageDocument_h - -#include "HTMLDocument.h" - -namespace WebCore { - -class ImageDocumentElement; - -class ImageDocument : public HTMLDocument { -public: - static PassRefPtr<ImageDocument> create(Frame* frame) - { - return new ImageDocument(frame); - } - - CachedImage* cachedImage(); - ImageDocumentElement* imageElement() const { return m_imageElement; } - void disconnectImageElement() { m_imageElement = 0; } - - void windowSizeChanged(); - void imageChanged(); - void imageClicked(int x, int y); - -private: - ImageDocument(Frame*); - - virtual Tokenizer* createTokenizer(); - virtual bool isImageDocument() const { return true; } - - void createDocumentStructure(); - void resizeImageToFit(); - void restoreImageSize(); - bool imageFitsInWindow() const; - bool shouldShrinkToFit() const; - float scale() const; - - ImageDocumentElement* m_imageElement; - - // Whether enough of the image has been loaded to determine its size - bool m_imageSizeIsKnown; - - // Whether the image is shrunk to fit or not - bool m_didShrinkImage; - - // Whether the image should be shrunk or not - bool m_shouldShrinkImage; -}; - -} - -#endif // ImageDocument_h diff --git a/WebCore/loader/ImageLoader.cpp b/WebCore/loader/ImageLoader.cpp deleted file mode 100644 index da159b4..0000000 --- a/WebCore/loader/ImageLoader.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "ImageLoader.h" - -#include "CSSHelper.h" -#include "CachedImage.h" -#include "DocLoader.h" -#include "Document.h" -#include "Element.h" -#include "RenderImage.h" - -namespace WebCore { - -ImageLoader::ImageLoader(Element* elt) - : m_element(elt) - , m_image(0) - , m_firedLoad(true) - , m_imageComplete(true) - , m_loadManually(false) -{ -} - -ImageLoader::~ImageLoader() -{ - if (m_image) - m_image->removeClient(this); - m_element->document()->removeImage(this); -} - -void ImageLoader::setImage(CachedImage* newImage) -{ - CachedImage* oldImage = m_image.get(); - if (newImage != oldImage) { - setLoadingImage(newImage); - m_firedLoad = true; - m_imageComplete = true; - if (newImage) - newImage->addClient(this); - if (oldImage) - oldImage->removeClient(this); - } - - if (RenderObject* renderer = element()->renderer()) { - if (!renderer->isImage()) - return; - - static_cast<RenderImage*>(renderer)->resetAnimation(); - } -} - -void ImageLoader::setLoadingImage(CachedImage* loadingImage) -{ - m_firedLoad = false; - m_imageComplete = false; - m_image = loadingImage; -} - -void ImageLoader::updateFromElement() -{ - // If we're not making renderers for the page, then don't load images. We don't want to slow - // down the raw HTML parsing case by loading images we don't intend to display. - Element* elem = element(); - Document* doc = elem->document(); - if (!doc->renderer()) - return; - - AtomicString attr = elem->getAttribute(elem->imageSourceAttributeName()); - - // Do not load any image if the 'src' attribute is missing or if it is - // an empty string referring to a local file. The latter condition is - // a quirk that preserves old behavior that Dashboard widgets - // need (<rdar://problem/5994621>). - CachedImage* newImage = 0; - if (!(attr.isNull() || attr.isEmpty() && doc->baseURI().isLocalFile())) { - if (m_loadManually) { - doc->docLoader()->setAutoLoadImages(false); - newImage = new CachedImage(sourceURI(attr)); - newImage->setLoading(true); - newImage->setDocLoader(doc->docLoader()); - doc->docLoader()->m_docResources.set(newImage->url(), newImage); - } else - newImage = doc->docLoader()->requestImage(sourceURI(attr)); - } - - CachedImage* oldImage = m_image.get(); - if (newImage != oldImage) { - setLoadingImage(newImage); - if (newImage) - newImage->addClient(this); - if (oldImage) - oldImage->removeClient(this); - } - - if (RenderObject* renderer = elem->renderer()) { - if (!renderer->isImage()) - return; - - static_cast<RenderImage*>(renderer)->resetAnimation(); - } -} - -void ImageLoader::notifyFinished(CachedResource *image) -{ - m_imageComplete = true; - - Element* elem = element(); - elem->document()->dispatchImageLoadEventSoon(this); - - if (RenderObject* renderer = elem->renderer()) { - if (!renderer->isImage()) - return; - - static_cast<RenderImage*>(renderer)->setCachedImage(m_image.get()); - } -} - -} diff --git a/WebCore/loader/ImageLoader.h b/WebCore/loader/ImageLoader.h deleted file mode 100644 index 39b5cc4..0000000 --- a/WebCore/loader/ImageLoader.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the DOM implementation for KDE. - * - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004 Apple Computer, Inc. - * - * 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. - * - */ - -#ifndef ImageLoader_h -#define ImageLoader_h - -#include "CachedResourceClient.h" -#include "CachedResourceHandle.h" - -namespace WebCore { - -class AtomicString; -class Element; - -class ImageLoader : public CachedResourceClient { -public: - ImageLoader(Element*); - virtual ~ImageLoader(); - - void updateFromElement(); - - virtual void dispatchLoadEvent() = 0; - virtual String sourceURI(const AtomicString&) const = 0; - - Element* element() const { return m_element; } - bool imageComplete() const { return m_imageComplete; } - - CachedImage* image() const { return m_image.get(); } - void setImage(CachedImage*); - - void setLoadManually(bool loadManually) { m_loadManually = loadManually; } - - // CachedResourceClient API - virtual void notifyFinished(CachedResource*); - - bool haveFiredLoadEvent() const { return m_firedLoad; } -protected: - void setLoadingImage(CachedImage*); - - void setHaveFiredLoadEvent(bool firedLoad) { m_firedLoad = firedLoad; } - -private: - Element* m_element; - CachedResourceHandle<CachedImage> m_image; - bool m_firedLoad : 1; - bool m_imageComplete : 1; - bool m_loadManually : 1; -}; - -} - -#endif diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp deleted file mode 100644 index 079bd79..0000000 --- a/WebCore/loader/MainResourceLoader.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "MainResourceLoader.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) -#include "ApplicationCache.h" -#include "ApplicationCacheGroup.h" -#include "ApplicationCacheResource.h" -#endif -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLFormElement.h" -#include "Page.h" -#include "ResourceError.h" -#include "ResourceHandle.h" -#include "Settings.h" - -// FIXME: More that is in common with SubresourceLoader should move up into ResourceLoader. - -namespace WebCore { - -MainResourceLoader::MainResourceLoader(Frame* frame) - : ResourceLoader(frame, true, true) - , m_dataLoadTimer(this, &MainResourceLoader::handleDataLoadNow) - , m_loadingMultipartContent(false) - , m_waitingForContentPolicy(false) -{ -} - -MainResourceLoader::~MainResourceLoader() -{ -} - -PassRefPtr<MainResourceLoader> MainResourceLoader::create(Frame* frame) -{ - return adoptRef(new MainResourceLoader(frame)); -} - -void MainResourceLoader::receivedError(const ResourceError& error) -{ - // Calling receivedMainResourceError will likely result in the last reference to this object to go away. - RefPtr<MainResourceLoader> protect(this); - RefPtr<Frame> protectFrame(m_frame); - - // It is important that we call FrameLoader::receivedMainResourceError before calling - // FrameLoader::didFailToLoad because receivedMainResourceError clears out the relevant - // document loaders. Also, receivedMainResourceError ends up calling a FrameLoadDelegate method - // and didFailToLoad calls a ResourceLoadDelegate method and they need to be in the correct order. - frameLoader()->receivedMainResourceError(error, true); - - if (!cancelled()) { - ASSERT(!reachedTerminalState()); - frameLoader()->didFailToLoad(this, error); - - releaseResources(); - } - - ASSERT(reachedTerminalState()); -} - -void MainResourceLoader::didCancel(const ResourceError& error) -{ - m_dataLoadTimer.stop(); - - // Calling receivedMainResourceError will likely result in the last reference to this object to go away. - RefPtr<MainResourceLoader> protect(this); - - if (m_waitingForContentPolicy) { - frameLoader()->cancelContentPolicyCheck(); - ASSERT(m_waitingForContentPolicy); - m_waitingForContentPolicy = false; - deref(); // balances ref in didReceiveResponse - } - frameLoader()->receivedMainResourceError(error, true); - ResourceLoader::didCancel(error); -} - -ResourceError MainResourceLoader::interruptionForPolicyChangeError() const -{ - return frameLoader()->interruptionForPolicyChangeError(request()); -} - -void MainResourceLoader::stopLoadingForPolicyChange() -{ - cancel(interruptionForPolicyChangeError()); -} - -void MainResourceLoader::callContinueAfterNavigationPolicy(void* argument, const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) -{ - static_cast<MainResourceLoader*>(argument)->continueAfterNavigationPolicy(request, shouldContinue); -} - -void MainResourceLoader::continueAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue) -{ - if (!shouldContinue) - stopLoadingForPolicyChange(); - deref(); // balances ref in willSendRequest -} - -bool MainResourceLoader::isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse) -{ - if (newRequest.httpMethod() == "POST") - return true; - - int status = redirectResponse.httpStatusCode(); - if (((status >= 301 && status <= 303) || status == 307) - && frameLoader()->initialRequest().httpMethod() == "POST") - return true; - - return false; -} - -void MainResourceLoader::addData(const char* data, int length, bool allAtOnce) -{ - ResourceLoader::addData(data, length, allAtOnce); - frameLoader()->receivedData(data, length); -} - -void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) -{ - // Note that there are no asserts here as there are for the other callbacks. This is due to the - // fact that this "callback" is sent when starting every load, and the state of callback - // deferrals plays less of a part in this function in preventing the bad behavior deferring - // callbacks is meant to prevent. - ASSERT(!newRequest.isNull()); - - // The additional processing can do anything including possibly removing the last - // reference to this object; one example of this is 3266216. - RefPtr<MainResourceLoader> protect(this); - - // Update cookie policy base URL as URL changes, except for subframes, which use the - // URL of the main frame which doesn't change when we redirect. - if (frameLoader()->isLoadingMainFrame()) - newRequest.setMainDocumentURL(newRequest.url()); - - // If we're fielding a redirect in response to a POST, force a load from origin, since - // this is a common site technique to return to a page viewing some data that the POST - // just modified. - // Also, POST requests always load from origin, but this does not affect subresources. - if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse)) - newRequest.setCachePolicy(ReloadIgnoringCacheData); - - ResourceLoader::willSendRequest(newRequest, redirectResponse); - - // Don't set this on the first request. It is set when the main load was started. - m_documentLoader->setRequest(newRequest); - - // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate - // listener. But there's no way to do that in practice. So instead we cancel later if the - // listener tells us to. In practice that means the navigation policy needs to be decided - // synchronously for these redirect cases. - - ref(); // balanced by deref in continueAfterNavigationPolicy - frameLoader()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this); -} - -static bool shouldLoadAsEmptyDocument(const KURL& url) -{ - return url.isEmpty() || equalIgnoringCase(String(url.protocol()), "about"); -} - -void MainResourceLoader::continueAfterContentPolicy(PolicyAction contentPolicy, const ResourceResponse& r) -{ - KURL url = request().url(); - const String& mimeType = r.mimeType(); - - switch (contentPolicy) { - case PolicyUse: { - // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255). - bool isRemoteWebArchive = equalIgnoringCase("application/x-webarchive", mimeType) && !m_substituteData.isValid() && !url.isLocalFile(); - if (!frameLoader()->canShowMIMEType(mimeType) || isRemoteWebArchive) { - frameLoader()->cannotShowMIMEType(r); - // Check reachedTerminalState since the load may have already been cancelled inside of _handleUnimplementablePolicyWithErrorCode::. - if (!reachedTerminalState()) - stopLoadingForPolicyChange(); - return; - } - break; - } - - case PolicyDownload: - frameLoader()->client()->download(m_handle.get(), request(), m_handle.get()->request(), r); - // It might have gone missing - if (frameLoader()) - receivedError(interruptionForPolicyChangeError()); - return; - - case PolicyIgnore: - stopLoadingForPolicyChange(); - return; - - default: - ASSERT_NOT_REACHED(); - } - - RefPtr<MainResourceLoader> protect(this); - - if (r.isHTTP()) { - int status = r.httpStatusCode(); - if (status < 200 || status >= 300) { - bool hostedByObject = frameLoader()->isHostedByObjectElement(); - - frameLoader()->handleFallbackContent(); - // object elements are no longer rendered after we fallback, so don't - // keep trying to process data from their load - - if (hostedByObject) - cancel(); - } - } - - // we may have cancelled this load as part of switching to fallback content - if (!reachedTerminalState()) - ResourceLoader::didReceiveResponse(r); - - if (frameLoader() && !frameLoader()->isStopping()) - if (m_substituteData.isValid()) { - if (m_substituteData.content()->size()) - didReceiveData(m_substituteData.content()->data(), m_substituteData.content()->size(), m_substituteData.content()->size(), true); - if (frameLoader() && !frameLoader()->isStopping()) - didFinishLoading(); - } else if (shouldLoadAsEmptyDocument(url) || frameLoader()->representationExistsForURLScheme(url.protocol())) - didFinishLoading(); -} - -void MainResourceLoader::callContinueAfterContentPolicy(void* argument, PolicyAction policy) -{ - static_cast<MainResourceLoader*>(argument)->continueAfterContentPolicy(policy); -} - -void MainResourceLoader::continueAfterContentPolicy(PolicyAction policy) -{ - ASSERT(m_waitingForContentPolicy); - m_waitingForContentPolicy = false; - if (frameLoader() && !frameLoader()->isStopping()) - continueAfterContentPolicy(policy, m_response); - deref(); // balances ref in didReceiveResponse -} - -void MainResourceLoader::didReceiveResponse(const ResourceResponse& r) -{ - // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. - // See <rdar://problem/6304600> for more details. -#if !PLATFORM(CF) - ASSERT(shouldLoadAsEmptyDocument(r.url()) || !defersLoading()); -#endif - - if (m_loadingMultipartContent) { - frameLoader()->setupForReplaceByMIMEType(r.mimeType()); - clearResourceData(); - } - - if (r.isMultipart()) - m_loadingMultipartContent = true; - - // The additional processing can do anything including possibly removing the last - // reference to this object; one example of this is 3266216. - RefPtr<MainResourceLoader> protect(this); - - m_documentLoader->setResponse(r); - - m_response = r; - - ASSERT(!m_waitingForContentPolicy); - m_waitingForContentPolicy = true; - ref(); // balanced by deref in continueAfterContentPolicy and didCancel - frameLoader()->checkContentPolicy(m_response.mimeType(), callContinueAfterContentPolicy, this); -} - -void MainResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) -{ - ASSERT(data); - ASSERT(length != 0); - - // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. - // See <rdar://problem/6304600> for more details. -#if !PLATFORM(CF) - ASSERT(!defersLoading()); -#endif - - // The additional processing can do anything including possibly removing the last - // reference to this object; one example of this is 3266216. - RefPtr<MainResourceLoader> protect(this); - - ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce); -} - -void MainResourceLoader::didFinishLoading() -{ - // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. - // See <rdar://problem/6304600> for more details. -#if !PLATFORM(CF) - ASSERT(shouldLoadAsEmptyDocument(frameLoader()->activeDocumentLoader()->url()) || !defersLoading()); -#endif - - // The additional processing can do anything including possibly removing the last - // reference to this object. - RefPtr<MainResourceLoader> protect(this); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - RefPtr<DocumentLoader> dl = documentLoader(); -#endif - - frameLoader()->finishedLoading(); - ResourceLoader::didFinishLoading(); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - ApplicationCacheGroup* group = dl->candidateApplicationCacheGroup(); - if (!group && dl->applicationCache() && !dl->mainResourceApplicationCache()) - group = dl->applicationCache()->group(); - - if (group) - group->finishedLoadingMainResource(dl.get()); -#endif -} - -void MainResourceLoader::didFail(const ResourceError& error) -{ - // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred. - // See <rdar://problem/6304600> for more details. -#if !PLATFORM(CF) - ASSERT(!defersLoading()); -#endif - - receivedError(error); -} - -void MainResourceLoader::handleEmptyLoad(const KURL& url, bool forURLScheme) -{ - String mimeType; - if (forURLScheme) - mimeType = frameLoader()->generatedMIMETypeForURLScheme(url.protocol()); - else - mimeType = "text/html"; - - ResourceResponse response(url, mimeType, 0, String(), String()); - didReceiveResponse(response); -} - -void MainResourceLoader::handleDataLoadNow(Timer<MainResourceLoader>*) -{ - RefPtr<MainResourceLoader> protect(this); - - KURL url = m_substituteData.responseURL(); - if (url.isEmpty()) - url = m_initialRequest.url(); - - ResourceResponse response(url, m_substituteData.mimeType(), m_substituteData.content()->size(), m_substituteData.textEncoding(), ""); - didReceiveResponse(response); -} - -void MainResourceLoader::handleDataLoadSoon(ResourceRequest& r) -{ - m_initialRequest = r; - - if (m_documentLoader->deferMainResourceDataLoad()) - m_dataLoadTimer.startOneShot(0); - else - handleDataLoadNow(0); -} - -bool MainResourceLoader::loadNow(ResourceRequest& r) -{ - bool shouldLoadEmptyBeforeRedirect = shouldLoadAsEmptyDocument(r.url()); - - ASSERT(!m_handle); - ASSERT(shouldLoadEmptyBeforeRedirect || !defersLoading()); - - // Send this synthetic delegate callback since clients expect it, and - // we no longer send the callback from within NSURLConnection for - // initial requests. - willSendRequest(r, ResourceResponse()); - - // <rdar://problem/4801066> - // willSendRequest() is liable to make the call to frameLoader() return NULL, so we need to check that here - if (!frameLoader()) - return false; - - const KURL& url = r.url(); - bool shouldLoadEmpty = shouldLoadAsEmptyDocument(url) && !m_substituteData.isValid(); - - if (shouldLoadEmptyBeforeRedirect && !shouldLoadEmpty && defersLoading()) - return true; - - if (m_substituteData.isValid()) - handleDataLoadSoon(r); - else if (shouldLoadEmpty || frameLoader()->representationExistsForURLScheme(url.protocol())) - handleEmptyLoad(url, !shouldLoadEmpty); - else - m_handle = ResourceHandle::create(r, this, m_frame.get(), false, true, true); - - return false; -} - -bool MainResourceLoader::load(const ResourceRequest& r, const SubstituteData& substituteData) -{ - ASSERT(!m_handle); - - m_substituteData = substituteData; - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - // Check if this request should be loaded from the application cache - if (!m_substituteData.isValid() && frameLoader()->frame()->settings() && frameLoader()->frame()->settings()->offlineWebApplicationCacheEnabled()) { - ASSERT(!m_applicationCache); - - if (Page* page = frameLoader()->frame()->page()) { - if (frameLoader()->frame() == page->mainFrame()) - m_applicationCache = ApplicationCacheGroup::cacheForMainRequest(r, m_documentLoader.get()); - else - m_applicationCache = frameLoader()->documentLoader()->topLevelApplicationCache(); - } - - if (m_applicationCache) { - // Get the resource from the application cache. - // FIXME: If the resource does not exist, the load should fail. - if (ApplicationCacheResource* resource = m_applicationCache->resourceForRequest(r)) { - m_substituteData = SubstituteData(resource->data(), - resource->response().mimeType(), - resource->response().textEncodingName(), KURL()); - } - } - } -#endif - - ResourceRequest request(r); - bool defer = defersLoading(); - if (defer) { - bool shouldLoadEmpty = shouldLoadAsEmptyDocument(r.url()); - if (shouldLoadEmpty) - defer = false; - } - if (!defer) { - if (loadNow(request)) { - // Started as an empty document, but was redirected to something non-empty. - ASSERT(defersLoading()); - defer = true; - } - } - if (defer) - m_initialRequest = request; - - return true; -} - -void MainResourceLoader::setDefersLoading(bool defers) -{ - ResourceLoader::setDefersLoading(defers); - - if (defers) { - if (m_dataLoadTimer.isActive()) - m_dataLoadTimer.stop(); - } else { - if (m_initialRequest.isNull()) - return; - - if (m_substituteData.isValid() && - m_documentLoader->deferMainResourceDataLoad()) - m_dataLoadTimer.startOneShot(0); - else { - ResourceRequest r(m_initialRequest); - m_initialRequest = ResourceRequest(); - loadNow(r); - } - } -} - -} diff --git a/WebCore/loader/MainResourceLoader.h b/WebCore/loader/MainResourceLoader.h deleted file mode 100644 index 6c69c1f..0000000 --- a/WebCore/loader/MainResourceLoader.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "FrameLoaderTypes.h" -#include "ResourceLoader.h" -#include "SubstituteData.h" -#include "Timer.h" -#include <wtf/Forward.h> - -namespace WebCore { - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - class ApplicationCache; -#endif - class FormState; - class ResourceRequest; - - class MainResourceLoader : public ResourceLoader { - public: - static PassRefPtr<MainResourceLoader> create(Frame*); - virtual ~MainResourceLoader(); - - virtual bool load(const ResourceRequest&, const SubstituteData&); - virtual void addData(const char*, int, bool allAtOnce); - - virtual void setDefersLoading(bool); - - virtual void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse); - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int, long long lengthReceived, bool allAtOnce); - virtual void didFinishLoading(); - virtual void didFail(const ResourceError&); - - void handleDataLoadNow(Timer<MainResourceLoader>*); - - bool isLoadingMultipartContent() const { return m_loadingMultipartContent; } - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - ApplicationCache* applicationCache() const { return m_applicationCache.get(); } -#endif - - private: - MainResourceLoader(Frame*); - - virtual void didCancel(const ResourceError&); - - bool loadNow(ResourceRequest&); - - void handleEmptyLoad(const KURL&, bool forURLScheme); - void handleDataLoadSoon(ResourceRequest& r); - - void handleDataLoad(ResourceRequest&); - - void receivedError(const ResourceError&); - ResourceError interruptionForPolicyChangeError() const; - void stopLoadingForPolicyChange(); - bool isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse); - - static void callContinueAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); - - static void callContinueAfterContentPolicy(void*, PolicyAction); - void continueAfterContentPolicy(PolicyAction); - void continueAfterContentPolicy(PolicyAction, const ResourceResponse&); - - ResourceRequest m_initialRequest; - SubstituteData m_substituteData; - Timer<MainResourceLoader> m_dataLoadTimer; - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - // The application cache that the main resource was loaded from (if any). - RefPtr<ApplicationCache> m_applicationCache; -#endif - - bool m_loadingMultipartContent; - bool m_waitingForContentPolicy; - }; - -} diff --git a/WebCore/loader/MediaDocument.cpp b/WebCore/loader/MediaDocument.cpp deleted file mode 100644 index 5689457..0000000 --- a/WebCore/loader/MediaDocument.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(VIDEO) -#include "MediaDocument.h" - -#include "DocumentLoader.h" -#include "Element.h" -#include "Event.h" -#include "EventNames.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLEmbedElement.h" -#include "HTMLNames.h" -#include "HTMLVideoElement.h" -#include "MainResourceLoader.h" -#include "Page.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "Text.h" -#include "XMLTokenizer.h" - -namespace WebCore { - -using namespace HTMLNames; - -class MediaTokenizer : public Tokenizer { -public: - MediaTokenizer(Document* doc) : m_doc(doc), m_mediaElement(0) {} - - virtual bool write(const SegmentedString&, bool appendData); - virtual void stopParsing(); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } - virtual bool writeRawData(const char* data, int len); - - void createDocumentStructure(); -private: - Document* m_doc; - HTMLMediaElement* m_mediaElement; -}; - -bool MediaTokenizer::write(const SegmentedString& s, bool appendData) -{ - ASSERT_NOT_REACHED(); - return false; -} - -void MediaTokenizer::createDocumentStructure() -{ - ExceptionCode ec; - RefPtr<Element> rootElement = m_doc->createElementNS(xhtmlNamespaceURI, "html", ec); - m_doc->appendChild(rootElement, ec); - - RefPtr<Element> body = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec); - body->setAttribute(styleAttr, "background-color: rgb(38,38,38);"); - - rootElement->appendChild(body, ec); - - RefPtr<Element> mediaElement = m_doc->createElementNS(xhtmlNamespaceURI, "video", ec); - - m_mediaElement = static_cast<HTMLVideoElement*>(mediaElement.get()); - m_mediaElement->setAttribute(controlsAttr, ""); - m_mediaElement->setAttribute(autoplayAttr, ""); - m_mediaElement->setAttribute(styleAttr, "margin: auto; position: absolute; top: 0; right: 0; bottom: 0; left: 0;"); - - m_mediaElement->setAttribute(nameAttr, "media"); - m_mediaElement->setSrc(m_doc->url()); - - body->appendChild(mediaElement, ec); - - Frame* frame = m_doc->frame(); - if (!frame) - return; - - frame->loader()->activeDocumentLoader()->mainResourceLoader()->setShouldBufferData(false); -} - -bool MediaTokenizer::writeRawData(const char* data, int len) -{ - ASSERT(!m_mediaElement); - if (m_mediaElement) - return false; - - createDocumentStructure(); - finish(); - return false; -} - -void MediaTokenizer::stopParsing() -{ - Tokenizer::stopParsing(); -} - -void MediaTokenizer::finish() -{ - if (!m_parserStopped) - m_doc->finishedParsing(); -} - -bool MediaTokenizer::isWaitingForScripts() const -{ - // A media document is never waiting for scripts - return false; -} - -MediaDocument::MediaDocument(Frame* frame) - : HTMLDocument(frame) -{ - setParseMode(Compat); -} - -Tokenizer* MediaDocument::createTokenizer() -{ - return new MediaTokenizer(this); -} - -void MediaDocument::defaultEventHandler(Event* event) -{ - // Match the default Quicktime plugin behavior to allow - // clicking and double-clicking to pause and play the media. - EventTargetNode* targetNode = event->target()->toNode(); - if (targetNode && targetNode->hasTagName(videoTag)) { - HTMLVideoElement* video = static_cast<HTMLVideoElement*>(targetNode); - ExceptionCode ec; - if (event->type() == eventNames().clickEvent) { - if (!video->canPlay()) { - video->pause(ec); - event->setDefaultHandled(); - } - } else if (event->type() == eventNames().dblclickEvent) { - if (video->canPlay()) { - video->play(ec); - event->setDefaultHandled(); - } - } - } -} - -} -#endif diff --git a/WebCore/loader/MediaDocument.h b/WebCore/loader/MediaDocument.h deleted file mode 100644 index e5167e4..0000000 --- a/WebCore/loader/MediaDocument.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef MediaDocument_h -#define MediaDocument_h - -#if ENABLE(VIDEO) - -#include "HTMLDocument.h" - -namespace WebCore { - -class MediaDocument : public HTMLDocument { -public: - static PassRefPtr<MediaDocument> create(Frame* frame) - { - return new MediaDocument(frame); - } - - virtual void defaultEventHandler(Event*); - -private: - MediaDocument(Frame*); - - virtual bool isMediaDocument() const { return true; } - virtual Tokenizer* createTokenizer(); -}; - -} - -#endif -#endif diff --git a/WebCore/loader/NavigationAction.cpp b/WebCore/loader/NavigationAction.cpp deleted file mode 100644 index 6bd65ae..0000000 --- a/WebCore/loader/NavigationAction.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NavigationAction.h" - -#include "Event.h" -#include "FrameLoader.h" - -namespace WebCore { - -static NavigationType navigationType(FrameLoadType frameLoadType, bool isFormSubmission, bool haveEvent) -{ - if (isFormSubmission) - return NavigationTypeFormSubmitted; - if (haveEvent) - return NavigationTypeLinkClicked; - if (frameLoadType == FrameLoadTypeReload) - return NavigationTypeReload; - if (isBackForwardLoadType(frameLoadType)) - return NavigationTypeBackForward; - return NavigationTypeOther; -} - -NavigationAction::NavigationAction() - : m_type(NavigationTypeOther) -{ -} - -NavigationAction::NavigationAction(const KURL& url, NavigationType type) - : m_URL(url) - , m_type(type) -{ -} - -NavigationAction::NavigationAction(const KURL& url, FrameLoadType frameLoadType, - bool isFormSubmission) - : m_URL(url) - , m_type(navigationType(frameLoadType, isFormSubmission, 0)) -{ -} - -NavigationAction::NavigationAction(const KURL& url, NavigationType type, PassRefPtr<Event> event) - : m_URL(url) - , m_type(type) - , m_event(event) -{ -} - -NavigationAction::NavigationAction(const KURL& url, FrameLoadType frameLoadType, - bool isFormSubmission, PassRefPtr<Event> event) - : m_URL(url) - , m_type(navigationType(frameLoadType, isFormSubmission, event)) - , m_event(event) -{ -} - -} diff --git a/WebCore/loader/NavigationAction.h b/WebCore/loader/NavigationAction.h deleted file mode 100644 index 0477c6e..0000000 --- a/WebCore/loader/NavigationAction.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef NavigationAction_h -#define NavigationAction_h - -#include "Event.h" -#include "FrameLoaderTypes.h" -#include "KURL.h" -#include <wtf/Forward.h> - -namespace WebCore { - - class NavigationAction { - public: - NavigationAction(); - NavigationAction(const KURL&, NavigationType); - NavigationAction(const KURL&, FrameLoadType, bool isFormSubmission); - NavigationAction(const KURL&, NavigationType, PassRefPtr<Event>); - NavigationAction(const KURL&, FrameLoadType, bool isFormSubmission, PassRefPtr<Event>); - - bool isEmpty() const { return m_URL.isEmpty(); } - - KURL url() const { return m_URL; } - NavigationType type() const { return m_type; } - const Event* event() const { return m_event.get(); } - - private: - KURL m_URL; - NavigationType m_type; - RefPtr<Event> m_event; - }; - -} - -#endif diff --git a/WebCore/loader/NetscapePlugInStreamLoader.cpp b/WebCore/loader/NetscapePlugInStreamLoader.cpp deleted file mode 100644 index e12ed07..0000000 --- a/WebCore/loader/NetscapePlugInStreamLoader.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "NetscapePlugInStreamLoader.h" - -#include "FrameLoader.h" -#include "DocumentLoader.h" - -namespace WebCore { - -NetscapePlugInStreamLoader::NetscapePlugInStreamLoader(Frame* frame, NetscapePlugInStreamLoaderClient* client) - : ResourceLoader(frame, true, true) - , m_client(client) -{ -} - -NetscapePlugInStreamLoader::~NetscapePlugInStreamLoader() -{ -} - -PassRefPtr<NetscapePlugInStreamLoader> NetscapePlugInStreamLoader::create(Frame* frame, NetscapePlugInStreamLoaderClient* client) -{ - return adoptRef(new NetscapePlugInStreamLoader(frame, client)); -} - -bool NetscapePlugInStreamLoader::isDone() const -{ - return !m_client; -} - -void NetscapePlugInStreamLoader::releaseResources() -{ - m_client = 0; - ResourceLoader::releaseResources(); -} - -void NetscapePlugInStreamLoader::didReceiveResponse(const ResourceResponse& response) -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_client->didReceiveResponse(this, response); - - // Don't continue if the stream is cancelled - if (!m_client) - return; - - ResourceLoader::didReceiveResponse(response); - - // Don't continue if the stream is cancelled - if (!m_client) - return; - - if (!response.isHTTP()) - return; - - if (m_client->wantsAllStreams()) - return; - - if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) - didCancel(frameLoader()->fileDoesNotExistError(response)); -} - -void NetscapePlugInStreamLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_client->didReceiveData(this, data, length); - - ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce); -} - -void NetscapePlugInStreamLoader::didFinishLoading() -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_documentLoader->removePlugInStreamLoader(this); - m_client->didFinishLoading(this); - ResourceLoader::didFinishLoading(); -} - -void NetscapePlugInStreamLoader::didFail(const ResourceError& error) -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_documentLoader->removePlugInStreamLoader(this); - m_client->didFail(this, error); - ResourceLoader::didFail(error); -} - -void NetscapePlugInStreamLoader::didCancel(const ResourceError& error) -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_client->didFail(this, error); - - // We need to remove the stream loader after the call to didFail, since didFail can - // spawn a new run loop and if the loader has been removed it won't be deferred when - // the document loader is asked to defer loading. - m_documentLoader->removePlugInStreamLoader(this); - - ResourceLoader::didCancel(error); -} - -} diff --git a/WebCore/loader/NetscapePlugInStreamLoader.h b/WebCore/loader/NetscapePlugInStreamLoader.h deleted file mode 100644 index 092c6fc..0000000 --- a/WebCore/loader/NetscapePlugInStreamLoader.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ResourceLoader.h" -#include <wtf/Forward.h> - -namespace WebCore { - - class NetscapePlugInStreamLoader; - - class NetscapePlugInStreamLoaderClient { - public: - virtual void didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse&) = 0; - virtual void didReceiveData(NetscapePlugInStreamLoader*, const char*, int) = 0; - virtual void didFail(NetscapePlugInStreamLoader*, const ResourceError&) = 0; - virtual void didFinishLoading(NetscapePlugInStreamLoader*) { } - virtual bool wantsAllStreams() const { return false; } - - protected: - virtual ~NetscapePlugInStreamLoaderClient() { } - }; - - class NetscapePlugInStreamLoader : public ResourceLoader { - public: - static PassRefPtr<NetscapePlugInStreamLoader> create(Frame*, NetscapePlugInStreamLoaderClient*); - virtual ~NetscapePlugInStreamLoader(); - - bool isDone() const; - - private: - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int, long long lengthReceived, bool allAtOnce); - virtual void didFinishLoading(); - virtual void didFail(const ResourceError&); - - virtual void releaseResources(); - - NetscapePlugInStreamLoader(Frame*, NetscapePlugInStreamLoaderClient*); - - virtual void didCancel(const ResourceError& error); - - NetscapePlugInStreamLoaderClient* m_client; - }; - -} diff --git a/WebCore/loader/PluginDocument.cpp b/WebCore/loader/PluginDocument.cpp deleted file mode 100644 index 8be6ae2..0000000 --- a/WebCore/loader/PluginDocument.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "PluginDocument.h" - -#include "DocumentLoader.h" -#include "Element.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLEmbedElement.h" -#include "HTMLNames.h" -#include "MainResourceLoader.h" -#include "Page.h" -#include "RenderWidget.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "Text.h" -#include "XMLTokenizer.h" - -namespace WebCore { - -using namespace HTMLNames; - -class PluginTokenizer : public Tokenizer { -public: - PluginTokenizer(Document* doc) : m_doc(doc), m_embedElement(0) {} - - virtual bool write(const SegmentedString&, bool appendData); - virtual void stopParsing(); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - virtual bool wantsRawData() const { return true; } - virtual bool writeRawData(const char* data, int len); - - void createDocumentStructure(); -private: - Document* m_doc; - HTMLEmbedElement* m_embedElement; -}; - -bool PluginTokenizer::write(const SegmentedString& s, bool appendData) -{ - ASSERT_NOT_REACHED(); - return false; -} - -void PluginTokenizer::createDocumentStructure() -{ - ExceptionCode ec; - RefPtr<Element> rootElement = m_doc->createElementNS(xhtmlNamespaceURI, "html", ec); - m_doc->appendChild(rootElement, ec); - - RefPtr<Element> body = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec); - body->setAttribute(marginwidthAttr, "0"); - body->setAttribute(marginheightAttr, "0"); - body->setAttribute(bgcolorAttr, "rgb(38,38,38)"); - - rootElement->appendChild(body, ec); - - RefPtr<Element> embedElement = m_doc->createElementNS(xhtmlNamespaceURI, "embed", ec); - - m_embedElement = static_cast<HTMLEmbedElement*>(embedElement.get()); - m_embedElement->setAttribute(widthAttr, "100%"); - m_embedElement->setAttribute(heightAttr, "100%"); - - m_embedElement->setAttribute(nameAttr, "plugin"); - m_embedElement->setSrc(m_doc->url().string()); - m_embedElement->setType(m_doc->frame()->loader()->responseMIMEType()); - - body->appendChild(embedElement, ec); -} - -bool PluginTokenizer::writeRawData(const char* data, int len) -{ - ASSERT(!m_embedElement); - if (m_embedElement) - return false; - - createDocumentStructure(); - - if (Frame* frame = m_doc->frame()) { - Settings* settings = frame->settings(); - if (settings && settings->arePluginsEnabled()) { - m_doc->updateLayout(); - - if (RenderWidget* renderer = static_cast<RenderWidget*>(m_embedElement->renderer())) { - frame->loader()->client()->redirectDataToPlugin(renderer->widget()); - frame->loader()->activeDocumentLoader()->mainResourceLoader()->setShouldBufferData(false); - } - - finish(); - } - } - - return false; -} - -void PluginTokenizer::stopParsing() -{ - Tokenizer::stopParsing(); -} - -void PluginTokenizer::finish() -{ - if (!m_parserStopped) - m_doc->finishedParsing(); -} - -bool PluginTokenizer::isWaitingForScripts() const -{ - // A plugin document is never waiting for scripts - return false; -} - -PluginDocument::PluginDocument(Frame* frame) - : HTMLDocument(frame) -{ - setParseMode(Compat); -} - -Tokenizer* PluginDocument::createTokenizer() -{ - return new PluginTokenizer(this); -} - -} diff --git a/WebCore/loader/PluginDocument.h b/WebCore/loader/PluginDocument.h deleted file mode 100644 index 35e4038..0000000 --- a/WebCore/loader/PluginDocument.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PluginDocument_h -#define PluginDocument_h - -#include "HTMLDocument.h" - -namespace WebCore { - -class PluginDocument : public HTMLDocument { -public: - static PassRefPtr<PluginDocument> create(Frame* frame) - { - return new PluginDocument(frame); - } - -private: - PluginDocument(Frame*); - - virtual bool isPluginDocument() const { return true; } - virtual Tokenizer* createTokenizer(); -}; - -} - -#endif // PluginDocument_h diff --git a/WebCore/loader/ProgressTracker.cpp b/WebCore/loader/ProgressTracker.cpp deleted file mode 100644 index 56aa976..0000000 --- a/WebCore/loader/ProgressTracker.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ProgressTracker.h" - -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "ResourceResponse.h" -#include "SystemTime.h" - -using std::min; - -namespace WebCore { - -// Always start progress at initialProgressValue. This helps provide feedback as -// soon as a load starts. -static const double initialProgressValue = 0.1; - -// Similarly, always leave space at the end. This helps show the user that we're not done -// until we're done. -static const double finalProgressValue = 0.9; // 1.0 - initialProgressValue - -static const int progressItemDefaultEstimatedLength = 1024 * 16; - -struct ProgressItem { - ProgressItem(long long length) - : bytesReceived(0) - , estimatedLength(length) { } - - long long bytesReceived; - long long estimatedLength; -}; - -ProgressTracker::ProgressTracker() - : m_uniqueIdentifier(0) - , m_totalPageAndResourceBytesToLoad(0) - , m_totalBytesReceived(0) - , m_lastNotifiedProgressValue(0) - , m_lastNotifiedProgressTime(0) - , m_progressNotificationInterval(0.02) - , m_progressNotificationTimeInterval(0.1) - , m_finalProgressChangedSent(false) - , m_progressValue(0) - , m_numProgressTrackedFrames(0) -{ -} - -ProgressTracker::~ProgressTracker() -{ - deleteAllValues(m_progressItems); -} - -double ProgressTracker::estimatedProgress() const -{ - return m_progressValue; -} - -void ProgressTracker::reset() -{ - deleteAllValues(m_progressItems); - m_progressItems.clear(); - - m_totalPageAndResourceBytesToLoad = 0; - m_totalBytesReceived = 0; - m_progressValue = 0; - m_lastNotifiedProgressValue = 0; - m_lastNotifiedProgressTime = 0; - m_finalProgressChangedSent = false; - m_numProgressTrackedFrames = 0; - m_originatingProgressFrame = 0; -} - -void ProgressTracker::progressStarted(Frame* frame) -{ - // LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame); - - frame->loader()->client()->willChangeEstimatedProgress(); - - if (m_numProgressTrackedFrames == 0 || m_originatingProgressFrame == frame) { - reset(); - m_progressValue = initialProgressValue; - m_originatingProgressFrame = frame; - - m_originatingProgressFrame->loader()->client()->postProgressStartedNotification(); - } - m_numProgressTrackedFrames++; - - frame->loader()->client()->didChangeEstimatedProgress(); -} - -void ProgressTracker::progressCompleted(Frame* frame) -{ - // LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame); - - if (m_numProgressTrackedFrames <= 0) - return; - - frame->loader()->client()->willChangeEstimatedProgress(); - - m_numProgressTrackedFrames--; - if (m_numProgressTrackedFrames == 0 || - (frame == m_originatingProgressFrame && m_numProgressTrackedFrames != 0)) - finalProgressComplete(); - - frame->loader()->client()->didChangeEstimatedProgress(); -} - -void ProgressTracker::finalProgressComplete() -{ - // LOG (Progress, ""); - - RefPtr<Frame> frame = m_originatingProgressFrame.release(); - - // Before resetting progress value be sure to send client a least one notification - // with final progress value. - if (!m_finalProgressChangedSent) { - m_progressValue = 1; - frame->loader()->client()->postProgressEstimateChangedNotification(); - } - - reset(); - - frame->loader()->client()->setMainFrameDocumentReady(true); - frame->loader()->client()->postProgressFinishedNotification(); -} - -void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response) -{ - // LOG (Progress, "_private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", _private->numProgressTrackedFrames, _private->originatingProgressFrame); - - if (m_numProgressTrackedFrames <= 0) - return; - - long long estimatedLength = response.expectedContentLength(); - if (estimatedLength < 0) - estimatedLength = progressItemDefaultEstimatedLength; - - m_totalPageAndResourceBytesToLoad += estimatedLength; - - if (ProgressItem* item = m_progressItems.get(identifier)) { - item->bytesReceived = 0; - item->estimatedLength = estimatedLength; - } else - m_progressItems.set(identifier, new ProgressItem(estimatedLength)); -} - -void ProgressTracker::incrementProgress(unsigned long identifier, const char*, int length) -{ - ProgressItem* item = m_progressItems.get(identifier); - - // FIXME: Can this ever happen? - if (!item) - return; - - m_originatingProgressFrame->loader()->client()->willChangeEstimatedProgress(); - - unsigned bytesReceived = length; - double increment, percentOfRemainingBytes; - long long remainingBytes, estimatedBytesForPendingRequests; - - item->bytesReceived += bytesReceived; - if (item->bytesReceived > item->estimatedLength) { - m_totalPageAndResourceBytesToLoad += ((item->bytesReceived * 2) - item->estimatedLength); - item->estimatedLength = item->bytesReceived * 2; - } - - int numPendingOrLoadingRequests = m_originatingProgressFrame->loader()->numPendingOrLoadingRequests(true); - estimatedBytesForPendingRequests = progressItemDefaultEstimatedLength * numPendingOrLoadingRequests; - remainingBytes = ((m_totalPageAndResourceBytesToLoad + estimatedBytesForPendingRequests) - m_totalBytesReceived); - if (remainingBytes > 0) // Prevent divide by 0. - percentOfRemainingBytes = (double)bytesReceived / (double)remainingBytes; - else - percentOfRemainingBytes = 1.0; - - // Treat the first layout as the half-way point. - double maxProgressValue = m_originatingProgressFrame->loader()->firstLayoutDone() ? finalProgressValue : .5; - increment = (maxProgressValue - m_progressValue) * percentOfRemainingBytes; - m_progressValue += increment; - m_progressValue = min(m_progressValue, maxProgressValue); - ASSERT(m_progressValue >= initialProgressValue); - - m_totalBytesReceived += bytesReceived; - - double now = currentTime(); - double notifiedProgressTimeDelta = now - m_lastNotifiedProgressTime; - - // LOG (Progress, "_private->progressValue %g, _private->numProgressTrackedFrames %d", _private->progressValue, _private->numProgressTrackedFrames); - double notificationProgressDelta = m_progressValue - m_lastNotifiedProgressValue; - if ((notificationProgressDelta >= m_progressNotificationInterval || - notifiedProgressTimeDelta >= m_progressNotificationTimeInterval) && - m_numProgressTrackedFrames > 0) { - if (!m_finalProgressChangedSent) { - if (m_progressValue == 1) - m_finalProgressChangedSent = true; - - m_originatingProgressFrame->loader()->client()->postProgressEstimateChangedNotification(); - - m_lastNotifiedProgressValue = m_progressValue; - m_lastNotifiedProgressTime = now; - } - } - - m_originatingProgressFrame->loader()->client()->didChangeEstimatedProgress(); -} - -void ProgressTracker::completeProgress(unsigned long identifier) -{ - ProgressItem* item = m_progressItems.get(identifier); - - // FIXME: Can this happen? - if (!item) - return; - - // Adjust the total expected bytes to account for any overage/underage. - long long delta = item->bytesReceived - item->estimatedLength; - m_totalPageAndResourceBytesToLoad += delta; - item->estimatedLength = item->bytesReceived; - - m_progressItems.remove(identifier); - delete item; -} - -unsigned long ProgressTracker::createUniqueIdentifier() -{ - return ++m_uniqueIdentifier; -} - - -} diff --git a/WebCore/loader/ProgressTracker.h b/WebCore/loader/ProgressTracker.h deleted file mode 100644 index b8d4532..0000000 --- a/WebCore/loader/ProgressTracker.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ProgressTracker_h -#define ProgressTracker_h - -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; -class ResourceResponse; -struct ProgressItem; - -class ProgressTracker : Noncopyable { -public: - ProgressTracker(); - ~ProgressTracker(); - - unsigned long createUniqueIdentifier(); - - double estimatedProgress() const; - - void progressStarted(Frame*); - void progressCompleted(Frame*); - - void incrementProgress(unsigned long identifier, const ResourceResponse&); - void incrementProgress(unsigned long identifier, const char*, int); - void completeProgress(unsigned long identifier); - - long long totalPageAndResourceBytesToLoad() const { return m_totalPageAndResourceBytesToLoad; } - long long totalBytesReceived() const { return m_totalBytesReceived; } - -private: - void reset(); - void finalProgressComplete(); - - unsigned long m_uniqueIdentifier; - - long long m_totalPageAndResourceBytesToLoad; - long long m_totalBytesReceived; - double m_lastNotifiedProgressValue; - double m_lastNotifiedProgressTime; - double m_progressNotificationInterval; - double m_progressNotificationTimeInterval; - bool m_finalProgressChangedSent; - double m_progressValue; - RefPtr<Frame> m_originatingProgressFrame; - - int m_numProgressTrackedFrames; - HashMap<unsigned long, ProgressItem*> m_progressItems; -}; - -} - -#endif diff --git a/WebCore/loader/Request.cpp b/WebCore/loader/Request.cpp deleted file mode 100644 index 7791a48..0000000 --- a/WebCore/loader/Request.cpp +++ /dev/null @@ -1,47 +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) 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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" -#include "Request.h" - -#include "CachedResource.h" - -namespace WebCore { - -Request::Request(DocLoader* docLoader, CachedResource* object, bool incremental, bool shouldSkipCanLoadCheck, bool sendResourceLoadCallbacks) - : m_object(object) - , m_docLoader(docLoader) - , m_incremental(incremental) - , m_multipart(false) - , m_shouldSkipCanLoadCheck(shouldSkipCanLoadCheck) - , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks) -{ - m_object->setRequest(this); -} - -Request::~Request() -{ - m_object->setRequest(0); -} - -} //namespace WebCore diff --git a/WebCore/loader/Request.h b/WebCore/loader/Request.h deleted file mode 100644 index 07d1b82..0000000 --- a/WebCore/loader/Request.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef Request_h -#define Request_h - -#include <wtf/Vector.h> - -namespace WebCore { - - class CachedResource; - class DocLoader; - - class Request { - public: - Request(DocLoader*, CachedResource*, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks); - ~Request(); - - Vector<char>& buffer() { return m_buffer; } - CachedResource* cachedResource() { return m_object; } - DocLoader* docLoader() { return m_docLoader; } - - bool isIncremental() { return m_incremental; } - void setIsIncremental(bool b = true) { m_incremental = b; } - - bool isMultipart() { return m_multipart; } - void setIsMultipart(bool b = true) { m_multipart = b; } - - bool shouldSkipCanLoadCheck() const { return m_shouldSkipCanLoadCheck; } - bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } - - private: - Vector<char> m_buffer; - CachedResource* m_object; - DocLoader* m_docLoader; - bool m_incremental; - bool m_multipart; - bool m_shouldSkipCanLoadCheck; - bool m_sendResourceLoadCallbacks; - }; - -} //namespace WebCore - -#endif // Request_h diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp deleted file mode 100644 index a6f90b3..0000000 --- a/WebCore/loader/ResourceLoader.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * (C) 2007 Graham Dennis (graham.dennis@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ResourceLoader.h" - -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "Page.h" -#include "ProgressTracker.h" -#include "ResourceHandle.h" -#include "ResourceError.h" -#include "Settings.h" -#include "SharedBuffer.h" - -namespace WebCore { - -PassRefPtr<SharedBuffer> ResourceLoader::resourceData() -{ - if (m_resourceData) - return m_resourceData; - - if (ResourceHandle::supportsBufferedData() && m_handle) - return m_handle->bufferedData(); - - return 0; -} - -ResourceLoader::ResourceLoader(Frame* frame, bool sendResourceLoadCallbacks, bool shouldContentSniff) - : m_frame(frame) - , m_documentLoader(frame->loader()->activeDocumentLoader()) - , m_identifier(0) - , m_reachedTerminalState(false) - , m_cancelled(false) - , m_calledDidFinishLoad(false) - , m_sendResourceLoadCallbacks(sendResourceLoadCallbacks) - , m_shouldContentSniff(shouldContentSniff) - , m_shouldBufferData(true) - , m_defersLoading(frame->page()->defersLoading()) -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - , m_wasLoadedFromApplicationCache(false) -#endif -{ -} - -ResourceLoader::~ResourceLoader() -{ - ASSERT(m_reachedTerminalState); -} - -void ResourceLoader::releaseResources() -{ - ASSERT(!m_reachedTerminalState); - - // It's possible that when we release the handle, it will be - // deallocated and release the last reference to this object. - // We need to retain to avoid accessing the object after it - // has been deallocated and also to avoid reentering this method. - RefPtr<ResourceLoader> protector(this); - - m_frame = 0; - m_documentLoader = 0; - - // We need to set reachedTerminalState to true before we release - // the resources to prevent a double dealloc of WebView <rdar://problem/4372628> - m_reachedTerminalState = true; - - m_identifier = 0; - - if (m_handle) { - // Clear out the ResourceHandle's client so that it doesn't try to call - // us back after we release it. - m_handle->setClient(0); - m_handle = 0; - } - - m_resourceData = 0; - m_deferredRequest = ResourceRequest(); -} - -bool ResourceLoader::load(const ResourceRequest& r) -{ - ASSERT(!m_handle); - ASSERT(m_deferredRequest.isNull()); - ASSERT(!m_documentLoader->isSubstituteLoadPending(this)); - - ResourceRequest clientRequest(r); - willSendRequest(clientRequest, ResourceResponse()); - if (clientRequest.isNull()) { - didFail(frameLoader()->cancelledError(r)); - return false; - } - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (m_documentLoader->scheduleArchiveLoad(this, clientRequest, r.url())) - return true; -#endif - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (m_documentLoader->scheduleApplicationCacheLoad(this, clientRequest, r.url())) { - m_wasLoadedFromApplicationCache = true; - return true; - } -#endif - - if (m_defersLoading) { - m_deferredRequest = clientRequest; - return true; - } - - m_handle = ResourceHandle::create(clientRequest, this, m_frame.get(), m_defersLoading, m_shouldContentSniff, true); - - return true; -} - -void ResourceLoader::setDefersLoading(bool defers) -{ - m_defersLoading = defers; - if (m_handle) - m_handle->setDefersLoading(defers); - if (!defers && !m_deferredRequest.isNull()) { - ResourceRequest request(m_deferredRequest); - m_deferredRequest = ResourceRequest(); - load(request); - } -} - -FrameLoader* ResourceLoader::frameLoader() const -{ - if (!m_frame) - return 0; - return m_frame->loader(); -} - -void ResourceLoader::setShouldBufferData(bool shouldBufferData) -{ - m_shouldBufferData = shouldBufferData; - - // Reset any already buffered data - if (!m_shouldBufferData) - m_resourceData = 0; -} - - -void ResourceLoader::addData(const char* data, int length, bool allAtOnce) -{ - if (!m_shouldBufferData) - return; - - if (allAtOnce) { - m_resourceData = SharedBuffer::create(data, length); - return; - } - - if (ResourceHandle::supportsBufferedData()) { - // Buffer data only if the connection has handed us the data because is has stopped buffering it. - if (m_resourceData) - m_resourceData->append(data, length); - } else { - if (!m_resourceData) - m_resourceData = SharedBuffer::create(data, length); - else - m_resourceData->append(data, length); - } -} - -void ResourceLoader::clearResourceData() -{ - if (m_resourceData) - m_resourceData->clear(); -} - -void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - - ASSERT(!m_reachedTerminalState); - - if (m_sendResourceLoadCallbacks) { - if (!m_identifier) { - m_identifier = m_frame->page()->progress()->createUniqueIdentifier(); - frameLoader()->assignIdentifierToInitialRequest(m_identifier, request); - } - - frameLoader()->willSendRequest(this, request, redirectResponse); - } - - m_request = request; -} - -void ResourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ -} - -void ResourceLoader::didReceiveResponse(const ResourceResponse& r) -{ - ASSERT(!m_reachedTerminalState); - - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - - m_response = r; - - if (FormData* data = m_request.httpBody()) - data->removeGeneratedFilesIfNeeded(); - - if (m_sendResourceLoadCallbacks) - frameLoader()->didReceiveResponse(this, m_response); -} - -void ResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) -{ - // The following assertions are not quite valid here, since a subclass - // might override didReceiveData in a way that invalidates them. This - // happens with the steps listed in 3266216 - // ASSERT(con == connection); - // ASSERT(!m_reachedTerminalState); - - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - - addData(data, length, allAtOnce); - // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. - // However, with today's computers and networking speeds, this won't happen in practice. - // Could be an issue with a giant local file. - if (m_sendResourceLoadCallbacks && m_frame) - frameLoader()->didReceiveData(this, data, length, static_cast<int>(lengthReceived)); -} - -void ResourceLoader::willStopBufferingData(const char* data, int length) -{ - if (!m_shouldBufferData) - return; - - ASSERT(!m_resourceData); - m_resourceData = SharedBuffer::create(data, length); -} - -void ResourceLoader::didFinishLoading() -{ - // If load has been cancelled after finishing (which could happen with a - // JavaScript that changes the window location), do nothing. - if (m_cancelled) - return; - ASSERT(!m_reachedTerminalState); - - didFinishLoadingOnePart(); - releaseResources(); -} - -void ResourceLoader::didFinishLoadingOnePart() -{ - if (m_cancelled) - return; - ASSERT(!m_reachedTerminalState); - - if (m_calledDidFinishLoad) - return; - m_calledDidFinishLoad = true; - if (m_sendResourceLoadCallbacks) - frameLoader()->didFinishLoad(this); -} - -void ResourceLoader::didFail(const ResourceError& error) -{ - if (m_cancelled) - return; - ASSERT(!m_reachedTerminalState); - - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - - if (FormData* data = m_request.httpBody()) - data->removeGeneratedFilesIfNeeded(); - - if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) - frameLoader()->didFailToLoad(this, error); - - releaseResources(); -} - -void ResourceLoader::didCancel(const ResourceError& error) -{ - ASSERT(!m_cancelled); - ASSERT(!m_reachedTerminalState); - - if (FormData* data = m_request.httpBody()) - data->removeGeneratedFilesIfNeeded(); - - // This flag prevents bad behavior when loads that finish cause the - // load itself to be cancelled (which could happen with a javascript that - // changes the window location). This is used to prevent both the body - // of this method and the body of connectionDidFinishLoading: running - // for a single delegate. Cancelling wins. - m_cancelled = true; - - if (m_handle) - m_handle->clearAuthentication(); - - m_documentLoader->cancelPendingSubstituteLoad(this); - if (m_handle) { - m_handle->cancel(); - m_handle = 0; - } - if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) - frameLoader()->didFailToLoad(this, error); - - releaseResources(); -} - -void ResourceLoader::cancel() -{ - cancel(ResourceError()); -} - -void ResourceLoader::cancel(const ResourceError& error) -{ - if (m_reachedTerminalState) - return; - if (!error.isNull()) - didCancel(error); - else - didCancel(cancelledError()); -} - -const ResourceResponse& ResourceLoader::response() const -{ - return m_response; -} - -ResourceError ResourceLoader::cancelledError() -{ - return frameLoader()->cancelledError(m_request); -} - -ResourceError ResourceLoader::blockedError() -{ - return frameLoader()->blockedError(m_request); -} - -ResourceError ResourceLoader::cannotShowURLError() -{ - return frameLoader()->cannotShowURLError(m_request); -} - -void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - willSendRequest(request, redirectResponse); -} - -void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - didSendData(bytesSent, totalBytesToBeSent); -} - -void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) -{ - didReceiveResponse(response); -} - -void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived) -{ - didReceiveData(data, length, lengthReceived, false); -} - -void ResourceLoader::didFinishLoading(ResourceHandle*) -{ - didFinishLoading(); -} - -void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error) -{ - didFail(error); -} - -void ResourceLoader::wasBlocked(ResourceHandle*) -{ - didFail(blockedError()); -} - -void ResourceLoader::cannotShowURL(ResourceHandle*) -{ - didFail(cannotShowURLError()); -} - -void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) -{ - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - frameLoader()->didReceiveAuthenticationChallenge(this, challenge); -} - -void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge) -{ - // Protect this in this delegate method since the additional processing can do - // anything including possibly derefing this; one example of this is Radar 3266216. - RefPtr<ResourceLoader> protector(this); - frameLoader()->didCancelAuthenticationChallenge(this, challenge); -} - -void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) -{ - cancel(); -} - -void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy) -{ - // When in private browsing mode, prevent caching to disk - if (policy == StorageAllowed && m_frame->settings()->privateBrowsingEnabled()) - policy = StorageAllowedInMemoryOnly; -} - -} diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h deleted file mode 100644 index 722f5fc..0000000 --- a/WebCore/loader/ResourceLoader.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ResourceLoader_h -#define ResourceLoader_h - -#include "ResourceHandleClient.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include <wtf/RefCounted.h> -#include "AuthenticationChallenge.h" -#include "KURL.h" - -#include <wtf/Forward.h> - -namespace WebCore { - - class DocumentLoader; - class Frame; - class FrameLoader; - class ResourceHandle; - class SharedBuffer; - - class ResourceLoader : public RefCounted<ResourceLoader>, protected ResourceHandleClient { - public: - virtual ~ResourceLoader(); - - void cancel(); - - virtual bool load(const ResourceRequest&); - - FrameLoader* frameLoader() const; - DocumentLoader* documentLoader() const { return m_documentLoader.get(); } - - virtual void cancel(const ResourceError&); - ResourceError cancelledError(); - ResourceError blockedError(); - ResourceError cannotShowURLError(); - - virtual void setDefersLoading(bool); - - void setIdentifier(unsigned long identifier) { m_identifier = identifier; } - unsigned long identifier() const { return m_identifier; } - - virtual void releaseResources(); - const ResourceResponse& response() const; - - virtual void addData(const char*, int, bool allAtOnce); - virtual PassRefPtr<SharedBuffer> resourceData(); - void clearResourceData(); - - virtual void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse); - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int, long long lengthReceived, bool allAtOnce); - void willStopBufferingData(const char*, int); - virtual void didFinishLoading(); - virtual void didFail(const ResourceError&); - - virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); - void didCancelAuthenticationChallenge(const AuthenticationChallenge&); - virtual void receivedCancellation(const AuthenticationChallenge&); - - // ResourceHandleClient - virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& redirectResponse); - virtual void didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); - virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); - virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived); - virtual void didFinishLoading(ResourceHandle*); - virtual void didFail(ResourceHandle*, const ResourceError&); - virtual void wasBlocked(ResourceHandle*); - virtual void cannotShowURL(ResourceHandle*); - virtual void willStopBufferingData(ResourceHandle*, const char* data, int length) { willStopBufferingData(data, length); } - virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didReceiveAuthenticationChallenge(challenge); } - virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didCancelAuthenticationChallenge(challenge); } - virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge& challenge) { receivedCancellation(challenge); } - virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&); -#if PLATFORM(MAC) - virtual NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse*); -#endif - - ResourceHandle* handle() const { return m_handle.get(); } - bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } - - void setShouldBufferData(bool shouldBufferData); - - protected: - ResourceLoader(Frame*, bool sendResourceLoadCallbacks, bool shouldContentSniff); - - virtual void didCancel(const ResourceError&); - void didFinishLoadingOnePart(); - - const ResourceRequest& request() const { return m_request; } - bool reachedTerminalState() const { return m_reachedTerminalState; } - bool cancelled() const { return m_cancelled; } - bool defersLoading() const { return m_defersLoading; } - - RefPtr<ResourceHandle> m_handle; - RefPtr<Frame> m_frame; - RefPtr<DocumentLoader> m_documentLoader; - ResourceResponse m_response; - - private: - ResourceRequest m_request; - RefPtr<SharedBuffer> m_resourceData; - - unsigned long m_identifier; - - bool m_reachedTerminalState; - bool m_cancelled; - bool m_calledDidFinishLoad; - - bool m_sendResourceLoadCallbacks; - bool m_shouldContentSniff; - bool m_shouldBufferData; - bool m_defersLoading; -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - bool m_wasLoadedFromApplicationCache; -#endif - ResourceRequest m_deferredRequest; - }; - -} - -#endif diff --git a/WebCore/loader/SubresourceLoader.cpp b/WebCore/loader/SubresourceLoader.cpp deleted file mode 100644 index bff48b2..0000000 --- a/WebCore/loader/SubresourceLoader.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "SubresourceLoader.h" - -#include "Document.h" -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "Logging.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "SubresourceLoaderClient.h" -#include "SharedBuffer.h" -#include <wtf/RefCountedLeakCounter.h> - -namespace WebCore { - -#ifndef NDEBUG -static WTF::RefCountedLeakCounter subresourceLoaderCounter("SubresourceLoader"); -#endif - -SubresourceLoader::SubresourceLoader(Frame* frame, SubresourceLoaderClient* client, bool sendResourceLoadCallbacks, bool shouldContentSniff) - : ResourceLoader(frame, sendResourceLoadCallbacks, shouldContentSniff) - , m_client(client) - , m_loadingMultipartContent(false) -{ -#ifndef NDEBUG - subresourceLoaderCounter.increment(); -#endif - m_documentLoader->addSubresourceLoader(this); -} - -SubresourceLoader::~SubresourceLoader() -{ -#ifndef NDEBUG - subresourceLoaderCounter.decrement(); -#endif -} - -bool SubresourceLoader::load(const ResourceRequest& r) -{ - m_frame->loader()->didTellClientAboutLoad(r.url().string()); - - return ResourceLoader::load(r); -} - -PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, bool skipCanLoadCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff) -{ - if (!frame) - return 0; - - FrameLoader* fl = frame->loader(); - if (!skipCanLoadCheck && fl->state() == FrameStateProvisional) - return 0; - - ResourceRequest newRequest = request; - - if (!skipCanLoadCheck - && FrameLoader::restrictAccessToLocal() - && !FrameLoader::canLoad(request.url(), String(), frame->document())) { - FrameLoader::reportLocalLoadFailed(frame, request.url().string()); - return 0; - } - - if (FrameLoader::shouldHideReferrer(request.url(), fl->outgoingReferrer())) - newRequest.clearHTTPReferrer(); - else if (!request.httpReferrer()) - newRequest.setHTTPReferrer(fl->outgoingReferrer()); - FrameLoader::addHTTPOriginIfNeeded(newRequest, fl->outgoingOrigin()); - - // Use the original request's cache policy for two reasons: - // 1. For POST requests, we mutate the cache policy for the main resource, - // but we do not want this to apply to subresources - // 2. Delegates that modify the cache policy using willSendRequest: should - // not affect any other resources. Such changes need to be done - // per request. - if (newRequest.isConditional()) - newRequest.setCachePolicy(ReloadIgnoringCacheData); - else - newRequest.setCachePolicy(fl->originalRequest().cachePolicy()); - - fl->addExtraFieldsToRequest(newRequest, false, false); - - RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff))); - if (!subloader->load(newRequest)) - return 0; - - return subloader.release(); -} - -void SubresourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse) -{ - // Store the previous URL because the call to ResourceLoader::willSendRequest will modify it. - KURL previousURL = request().url(); - - ResourceLoader::willSendRequest(newRequest, redirectResponse); - if (!previousURL.isNull() && !newRequest.isNull() && previousURL != newRequest.url() && m_client) - m_client->willSendRequest(this, newRequest, redirectResponse); -} - -void SubresourceLoader::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didSendData(this, bytesSent, totalBytesToBeSent); -} - -void SubresourceLoader::didReceiveResponse(const ResourceResponse& r) -{ - ASSERT(!r.isNull()); - - if (r.isMultipart()) - m_loadingMultipartContent = true; - - // Reference the object in this method since the additional processing can do - // anything including removing the last reference to this object; one example of this is 3266216. - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didReceiveResponse(this, r); - - // The loader can cancel a load if it receives a multipart response for a non-image - if (reachedTerminalState()) - return; - ResourceLoader::didReceiveResponse(r); - - RefPtr<SharedBuffer> buffer = resourceData(); - if (m_loadingMultipartContent && buffer && buffer->size()) { - // Since a subresource loader does not load multipart sections progressively, - // deliver the previously received data to the loader all at once now. - // Then clear the data to make way for the next multipart section. - if (m_client) - m_client->didReceiveData(this, buffer->data(), buffer->size()); - clearResourceData(); - - // After the first multipart section is complete, signal to delegates that this load is "finished" - m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this); - didFinishLoadingOnePart(); - } -} - -void SubresourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) -{ - // Reference the object in this method since the additional processing can do - // anything including removing the last reference to this object; one example of this is 3266216. - RefPtr<SubresourceLoader> protect(this); - - ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce); - - // A subresource loader does not load multipart sections progressively. - // So don't deliver any data to the loader yet. - if (!m_loadingMultipartContent && m_client) - m_client->didReceiveData(this, data, length); -} - -void SubresourceLoader::didFinishLoading() -{ - if (cancelled()) - return; - ASSERT(!reachedTerminalState()); - - // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves. - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didFinishLoading(this); - - m_handle = 0; - - if (cancelled()) - return; - m_documentLoader->removeSubresourceLoader(this); - ResourceLoader::didFinishLoading(); -} - -void SubresourceLoader::didFail(const ResourceError& error) -{ - if (cancelled()) - return; - ASSERT(!reachedTerminalState()); - - // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves. - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didFail(this, error); - - m_handle = 0; - - if (cancelled()) - return; - m_documentLoader->removeSubresourceLoader(this); - ResourceLoader::didFail(error); -} - -void SubresourceLoader::didCancel(const ResourceError& error) -{ - ASSERT(!reachedTerminalState()); - - // Calling removeSubresourceLoader will likely result in a call to deref, so we must protect ourselves. - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didFail(this, error); - - if (cancelled()) - return; - m_documentLoader->removeSubresourceLoader(this); - ResourceLoader::didCancel(error); -} - -void SubresourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) -{ - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->didReceiveAuthenticationChallenge(this, challenge); - - // The SubResourceLoaderClient may have cancelled this ResourceLoader in response to the challenge. - // If that's the case, don't call didReceiveAuthenticationChallenge - if (reachedTerminalState()) - return; - - ResourceLoader::didReceiveAuthenticationChallenge(challenge); -} - -void SubresourceLoader::receivedCancellation(const AuthenticationChallenge& challenge) -{ - ASSERT(!reachedTerminalState()); - - RefPtr<SubresourceLoader> protect(this); - - if (m_client) - m_client->receivedCancellation(this, challenge); - - ResourceLoader::receivedCancellation(challenge); -} - - -} diff --git a/WebCore/loader/SubresourceLoader.h b/WebCore/loader/SubresourceLoader.h deleted file mode 100644 index b5bd34a..0000000 --- a/WebCore/loader/SubresourceLoader.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SubresourceLoader_h -#define SubresourceLoader_h - -#include "ResourceHandleClient.h" -#include "ResourceLoader.h" -#include <wtf/PassRefPtr.h> - -namespace WebCore { - - class FormData; - class String; - class ResourceHandle; - class ResourceRequest; - class SubresourceLoaderClient; - - class SubresourceLoader : public ResourceLoader { - public: - static PassRefPtr<SubresourceLoader> create(Frame*, SubresourceLoaderClient*, const ResourceRequest&, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true); - - virtual ~SubresourceLoader(); - - virtual bool load(const ResourceRequest&); - - virtual void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse); - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int, long long lengthReceived, bool allAtOnce); - virtual void didFinishLoading(); - virtual void didFail(const ResourceError&); - virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); - virtual void receivedCancellation(const AuthenticationChallenge&); - - void clearClient() { m_client = 0; } - - private: - SubresourceLoader(Frame*, SubresourceLoaderClient*, bool sendResourceLoadCallbacks, bool shouldContentSniff); - - virtual void didCancel(const ResourceError&); - SubresourceLoaderClient* m_client; - bool m_loadingMultipartContent; - }; - -} - -#endif // SubresourceLoader_h diff --git a/WebCore/loader/SubresourceLoaderClient.h b/WebCore/loader/SubresourceLoaderClient.h deleted file mode 100644 index d2b9a12..0000000 --- a/WebCore/loader/SubresourceLoaderClient.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SubresourceLoaderClient_h -#define SubresourceLoaderClient_h - -namespace WebCore { - -class AuthenticationChallenge; -class ResourceError; -class ResourceRequest; -class ResourceResponse; -class SubresourceLoader; - -class SubresourceLoaderClient { -public: - virtual ~SubresourceLoaderClient() { } - - // request may be modified - virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse) { } - virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { } - - virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&) { } - virtual void didReceiveData(SubresourceLoader*, const char*, int) { } - virtual void didFinishLoading(SubresourceLoader*) { } - virtual void didFail(SubresourceLoader*, const ResourceError&) { } - - virtual void didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&) { } - virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&) { } - -}; - -} // namespace WebCore - -#endif // SubresourceLoaderClient_h diff --git a/WebCore/loader/SubstituteData.h b/WebCore/loader/SubstituteData.h deleted file mode 100644 index 0b87b62..0000000 --- a/WebCore/loader/SubstituteData.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SubstituteData_h -#define SubstituteData_h - -#include "KURL.h" -#include "SharedBuffer.h" -#include "PlatformString.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - - class SubstituteData { - public: - SubstituteData() { } - - SubstituteData(PassRefPtr<SharedBuffer> content, const String& mimeType, const String& textEncoding, const KURL& failingURL, const KURL& responseURL = KURL()) - : m_content(content) - , m_mimeType(mimeType) - , m_textEncoding(textEncoding) - , m_failingURL(failingURL) - , m_responseURL(responseURL) - { - } - - bool isValid() const { return m_content != 0; } - - const SharedBuffer* content() const { return m_content.get(); } - const String& mimeType() const { return m_mimeType; } - const String& textEncoding() const { return m_textEncoding; } - const KURL& failingURL() const { return m_failingURL; } - const KURL& responseURL() const { return m_responseURL; } - - private: - RefPtr<SharedBuffer> m_content; - String m_mimeType; - String m_textEncoding; - KURL m_failingURL; - KURL m_responseURL; - }; - -} - -#endif // SubstituteData_h - diff --git a/WebCore/loader/SubstituteResource.h b/WebCore/loader/SubstituteResource.h deleted file mode 100644 index 15cbc6f..0000000 --- a/WebCore/loader/SubstituteResource.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SubstituteResource_h -#define SubstituteResource_h - -#include <wtf/RefCounted.h> - -#include "KURL.h" -#include "ResourceResponse.h" -#include "SharedBuffer.h" - -#include <wtf/RefPtr.h> - -namespace WebCore { - -class SubstituteResource : public RefCounted<SubstituteResource> { -public: - virtual ~SubstituteResource() { } - - const KURL& url() const { return m_url; } - const ResourceResponse& response() const { return m_response; } - SharedBuffer* data() const { return m_data.get(); } - -protected: - SubstituteResource(const KURL& url, const ResourceResponse& response, PassRefPtr<SharedBuffer> data) - : m_url(url) - , m_response(response) - , m_data(data) - { - ASSERT(m_data); - } - -private: - KURL m_url; - ResourceResponse m_response; - RefPtr<SharedBuffer> m_data; -}; - -} - -#endif // SubstituteResource_h diff --git a/WebCore/loader/TextDocument.cpp b/WebCore/loader/TextDocument.cpp deleted file mode 100644 index 6b06ede..0000000 --- a/WebCore/loader/TextDocument.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "TextDocument.h" - -#include "Element.h" -#include "HTMLNames.h" -#include "HTMLViewSourceDocument.h" -#include "SegmentedString.h" -#include "Text.h" -#include "XMLTokenizer.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -class TextTokenizer : public Tokenizer { -public: - TextTokenizer(Document*); - TextTokenizer(HTMLViewSourceDocument*); - - virtual bool write(const SegmentedString&, bool appendData); - virtual void finish(); - virtual bool isWaitingForScripts() const; - - inline void checkBuffer(int len = 10) - { - if ((m_dest - m_buffer) > m_size - len) { - // Enlarge buffer - int newSize = std::max(m_size * 2, m_size + len); - int oldOffset = m_dest - m_buffer; - m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar))); - m_dest = m_buffer + oldOffset; - m_size = newSize; - } - } - -private: - Document* m_doc; - Element* m_preElement; - - bool m_skipLF; - - int m_size; - UChar* m_buffer; - UChar* m_dest; -}; - -TextTokenizer::TextTokenizer(Document* doc) - : m_doc(doc) - , m_preElement(0) - , m_skipLF(false) -{ - // Allocate buffer - m_size = 254; - m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size)); - m_dest = m_buffer; -} - -TextTokenizer::TextTokenizer(HTMLViewSourceDocument* doc) - : Tokenizer(true) - , m_doc(doc) - , m_preElement(0) - , m_skipLF(false) -{ - // Allocate buffer - m_size = 254; - m_buffer = static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size)); - m_dest = m_buffer; -} - -bool TextTokenizer::write(const SegmentedString& s, bool appendData) -{ - ExceptionCode ec; - - m_dest = m_buffer; - - SegmentedString str = s; - while (!str.isEmpty()) { - UChar c = *str; - - if (c == '\r') { - *m_dest++ = '\n'; - - // possibly skip an LF in the case of an CRLF sequence - m_skipLF = true; - } else if (c == '\n') { - if (!m_skipLF) - *m_dest++ = c; - else - m_skipLF = false; - } else { - *m_dest++ = c; - m_skipLF = false; - } - - str.advance(); - - // Maybe enlarge the buffer - checkBuffer(); - } - - if (!m_preElement && !inViewSourceMode()) { - RefPtr<Element> rootElement = m_doc->createElementNS(xhtmlNamespaceURI, "html", ec); - m_doc->appendChild(rootElement, ec); - - RefPtr<Element> body = m_doc->createElementNS(xhtmlNamespaceURI, "body", ec); - rootElement->appendChild(body, ec); - - RefPtr<Element> preElement = m_doc->createElementNS(xhtmlNamespaceURI, "pre", ec); - preElement->setAttribute("style", "word-wrap: break-word; white-space: pre-wrap;", ec); - - body->appendChild(preElement, ec); - - m_preElement = preElement.get(); - } - - String string = String(m_buffer, m_dest - m_buffer); - if (inViewSourceMode()) { - static_cast<HTMLViewSourceDocument*>(m_doc)->addViewSourceText(string); - return false; - } - - unsigned charsLeft = string.length(); - while (charsLeft) { - // split large text to nodes of manageable size - RefPtr<Text> text = Text::createWithLengthLimit(m_doc, string, charsLeft); - m_preElement->appendChild(text, ec); - } - - return false; -} - -void TextTokenizer::finish() -{ - m_preElement = 0; - fastFree(m_buffer); - - m_doc->finishedParsing(); -} - -bool TextTokenizer::isWaitingForScripts() const -{ - // A text document is never waiting for scripts - return false; -} - -TextDocument::TextDocument(Frame* frame) - : HTMLDocument(frame) -{ -} - -Tokenizer* TextDocument::createTokenizer() -{ - return new TextTokenizer(this); -} - -Tokenizer* createTextTokenizer(HTMLViewSourceDocument* document) -{ - return new TextTokenizer(document); -} - -} diff --git a/WebCore/loader/TextDocument.h b/WebCore/loader/TextDocument.h deleted file mode 100644 index c67fea5..0000000 --- a/WebCore/loader/TextDocument.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TextDocument_h -#define TextDocument_h - -#include "HTMLDocument.h" - -namespace WebCore { - -class HTMLViewSourceDocument; - -class TextDocument : public HTMLDocument { -public: - static PassRefPtr<TextDocument> create(Frame* frame) - { - return new TextDocument(frame); - } - -private: - TextDocument(Frame*); - - virtual Tokenizer* createTokenizer(); -}; - -Tokenizer* createTextTokenizer(HTMLViewSourceDocument*); - -} - -#endif // TextDocument_h diff --git a/WebCore/loader/TextResourceDecoder.cpp b/WebCore/loader/TextResourceDecoder.cpp deleted file mode 100644 index 4a0caa0..0000000 --- a/WebCore/loader/TextResourceDecoder.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/* - Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - Copyright (C) 2005, 2006, 2007 Alexey Proskuryakov (ap@nypop.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. -*/ - - -#include "config.h" -#include "TextResourceDecoder.h" - -#include "DOMImplementation.h" -#include "HTMLNames.h" -#include "TextCodec.h" -#include <wtf/ASCIICType.h> -#include <wtf/StringExtras.h> - -using namespace WTF; - -namespace WebCore { - -using namespace HTMLNames; - -// You might think we should put these find functions elsewhere, perhaps with the -// similar functions that operate on UChar, but arguably only the decoder has -// a reason to process strings of char rather than UChar. - -static int find(const char* subject, size_t subjectLength, const char* target) -{ - size_t targetLength = strlen(target); - if (targetLength > subjectLength) - return -1; - for (size_t i = 0; i <= subjectLength - targetLength; ++i) { - bool match = true; - for (size_t j = 0; j < targetLength; ++j) { - if (subject[i + j] != target[j]) { - match = false; - break; - } - } - if (match) - return i; - } - return -1; -} - -static int findIgnoringCase(const char* subject, size_t subjectLength, const char* target) -{ - size_t targetLength = strlen(target); - if (targetLength > subjectLength) - return -1; -#ifndef NDEBUG - for (size_t i = 0; i < targetLength; ++i) - ASSERT(isASCIILower(target[i])); -#endif - for (size_t i = 0; i <= subjectLength - targetLength; ++i) { - bool match = true; - for (size_t j = 0; j < targetLength; ++j) { - if (toASCIILower(subject[i + j]) != target[j]) { - match = false; - break; - } - } - if (match) - return i; - } - return -1; -} - -static TextEncoding findTextEncoding(const char* encodingName, int length) -{ - Vector<char, 64> buffer(length + 1); - memcpy(buffer.data(), encodingName, length); - buffer[length] = '\0'; - return buffer.data(); -} - -class KanjiCode { -public: - enum Type { ASCII, JIS, EUC, SJIS, UTF16, UTF8 }; - static enum Type judge(const char* str, int length); - static const int ESC = 0x1b; - static const unsigned char sjisMap[256]; - static int ISkanji(int code) - { - if (code >= 0x100) - return 0; - return sjisMap[code & 0xff] & 1; - } - static int ISkana(int code) - { - if (code >= 0x100) - return 0; - return sjisMap[code & 0xff] & 2; - } -}; - -const unsigned char KanjiCode::sjisMap[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 -}; - -/* - * EUC-JP is - * [0xa1 - 0xfe][0xa1 - 0xfe] - * 0x8e[0xa1 - 0xfe](SS2) - * 0x8f[0xa1 - 0xfe][0xa1 - 0xfe](SS3) - * - * Shift_Jis is - * [0x81 - 0x9f, 0xe0 - 0xef(0xfe?)][0x40 - 0x7e, 0x80 - 0xfc] - * - * Shift_Jis Hankaku Kana is - * [0xa1 - 0xdf] - */ - -/* - * KanjiCode::judge() is based on judge_jcode() from jvim - * http://hp.vector.co.jp/authors/VA003457/vim/ - * - * Special Thanks to Kenichi Tsuchida - */ - -enum KanjiCode::Type KanjiCode::judge(const char* str, int size) -{ - enum Type code; - int i; - int bfr = false; /* Kana Moji */ - int bfk = 0; /* EUC Kana */ - int sjis = 0; - int euc = 0; - - const unsigned char* ptr = reinterpret_cast<const unsigned char*>(str); - - code = ASCII; - - i = 0; - while (i < size) { - if (ptr[i] == ESC && (size - i >= 3)) { - if ((ptr[i + 1] == '$' && ptr[i + 2] == 'B') - || (ptr[i + 1] == '(' && ptr[i + 2] == 'B')) { - code = JIS; - goto breakBreak; - } else if ((ptr[i + 1] == '$' && ptr[i + 2] == '@') - || (ptr[i + 1] == '(' && ptr[i + 2] == 'J')) { - code = JIS; - goto breakBreak; - } else if (ptr[i + 1] == '(' && ptr[i + 2] == 'I') { - code = JIS; - i += 3; - } else if (ptr[i + 1] == ')' && ptr[i + 2] == 'I') { - code = JIS; - i += 3; - } else { - i++; - } - bfr = false; - bfk = 0; - } else { - if (ptr[i] < 0x20) { - bfr = false; - bfk = 0; - /* ?? check kudokuten ?? && ?? hiragana ?? */ - if ((i >= 2) && (ptr[i - 2] == 0x81) - && (0x41 <= ptr[i - 1] && ptr[i - 1] <= 0x49)) { - code = SJIS; - sjis += 100; /* kudokuten */ - } else if ((i >= 2) && (ptr[i - 2] == 0xa1) - && (0xa2 <= ptr[i - 1] && ptr[i - 1] <= 0xaa)) { - code = EUC; - euc += 100; /* kudokuten */ - } else if ((i >= 2) && (ptr[i - 2] == 0x82) && (0xa0 <= ptr[i - 1])) { - sjis += 40; /* hiragana */ - } else if ((i >= 2) && (ptr[i - 2] == 0xa4) && (0xa0 <= ptr[i - 1])) { - euc += 40; /* hiragana */ - } - } else { - /* ?? check hiragana or katana ?? */ - if ((size - i > 1) && (ptr[i] == 0x82) && (0xa0 <= ptr[i + 1])) { - sjis++; /* hiragana */ - } else if ((size - i > 1) && (ptr[i] == 0x83) - && (0x40 <= ptr[i + 1] && ptr[i + 1] <= 0x9f)) { - sjis++; /* katakana */ - } else if ((size - i > 1) && (ptr[i] == 0xa4) && (0xa0 <= ptr[i + 1])) { - euc++; /* hiragana */ - } else if ((size - i > 1) && (ptr[i] == 0xa5) && (0xa0 <= ptr[i + 1])) { - euc++; /* katakana */ - } - if (bfr) { - if ((i >= 1) && (0x40 <= ptr[i] && ptr[i] <= 0xa0) && ISkanji(ptr[i - 1])) { - code = SJIS; - goto breakBreak; - } else if ((i >= 1) && (0x81 <= ptr[i - 1] && ptr[i - 1] <= 0x9f) && ((0x40 <= ptr[i] && ptr[i] < 0x7e) || (0x7e < ptr[i] && ptr[i] <= 0xfc))) { - code = SJIS; - goto breakBreak; - } else if ((i >= 1) && (0xfd <= ptr[i] && ptr[i] <= 0xfe) && (0xa1 <= ptr[i - 1] && ptr[i - 1] <= 0xfe)) { - code = EUC; - goto breakBreak; - } else if ((i >= 1) && (0xfd <= ptr[i - 1] && ptr[i - 1] <= 0xfe) && (0xa1 <= ptr[i] && ptr[i] <= 0xfe)) { - code = EUC; - goto breakBreak; - } else if ((i >= 1) && (ptr[i] < 0xa0 || 0xdf < ptr[i]) && (0x8e == ptr[i - 1])) { - code = SJIS; - goto breakBreak; - } else if (ptr[i] <= 0x7f) { - code = SJIS; - goto breakBreak; - } else { - if (0xa1 <= ptr[i] && ptr[i] <= 0xa6) { - euc++; /* sjis hankaku kana kigo */ - } else if (0xa1 <= ptr[i] && ptr[i] <= 0xdf) { - ; /* sjis hankaku kana */ - } else if (0xa1 <= ptr[i] && ptr[i] <= 0xfe) { - euc++; - } else if (0x8e == ptr[i]) { - euc++; - } else if (0x20 <= ptr[i] && ptr[i] <= 0x7f) { - sjis++; - } - bfr = false; - bfk = 0; - } - } else if (0x8e == ptr[i]) { - if (size - i <= 1) { - ; - } else if (0xa1 <= ptr[i + 1] && ptr[i + 1] <= 0xdf) { - /* EUC KANA or SJIS KANJI */ - if (bfk == 1) { - euc += 100; - } - bfk++; - i++; - } else { - /* SJIS only */ - code = SJIS; - goto breakBreak; - } - } else if (0x81 <= ptr[i] && ptr[i] <= 0x9f) { - /* SJIS only */ - code = SJIS; - if ((size - i >= 1) - && ((0x40 <= ptr[i + 1] && ptr[i + 1] <= 0x7e) - || (0x80 <= ptr[i + 1] && ptr[i + 1] <= 0xfc))) { - goto breakBreak; - } - } else if (0xfd <= ptr[i] && ptr[i] <= 0xfe) { - /* EUC only */ - code = EUC; - if ((size - i >= 1) - && (0xa1 <= ptr[i + 1] && ptr[i + 1] <= 0xfe)) { - goto breakBreak; - } - } else if (ptr[i] <= 0x7f) { - ; - } else { - bfr = true; - bfk = 0; - } - } - i++; - } - } - if (code == ASCII) { - if (sjis > euc) { - code = SJIS; - } else if (sjis < euc) { - code = EUC; - } - } -breakBreak: - return (code); -} - -TextResourceDecoder::ContentType TextResourceDecoder::determineContentType(const String& mimeType) -{ - if (equalIgnoringCase(mimeType, "text/css")) - return CSS; - if (equalIgnoringCase(mimeType, "text/html")) - return HTML; - if (DOMImplementation::isXMLMIMEType(mimeType)) - return XML; - return PlainText; -} - -const TextEncoding& TextResourceDecoder::defaultEncoding(ContentType contentType, const TextEncoding& specifiedDefaultEncoding) -{ - // Despite 8.5 "Text/xml with Omitted Charset" of RFC 3023, we assume UTF-8 instead of US-ASCII - // for text/xml. This matches Firefox. - if (contentType == XML) - return UTF8Encoding(); - if (!specifiedDefaultEncoding.isValid()) - return Latin1Encoding(); - return specifiedDefaultEncoding; -} - -TextResourceDecoder::TextResourceDecoder(const String& mimeType, const TextEncoding& specifiedDefaultEncoding) - : m_contentType(determineContentType(mimeType)) - , m_decoder(defaultEncoding(m_contentType, specifiedDefaultEncoding)) - , m_source(DefaultEncoding) - , m_checkedForBOM(false) - , m_checkedForCSSCharset(false) - , m_checkedForHeadCharset(false) - , m_sawError(false) -{ -} - -TextResourceDecoder::~TextResourceDecoder() -{ -} - -void TextResourceDecoder::setEncoding(const TextEncoding& encoding, EncodingSource source) -{ - // In case the encoding didn't exist, we keep the old one (helps some sites specifying invalid encodings). - if (!encoding.isValid()) - return; - - // When encoding comes from meta tag (i.e. it cannot be XML files sent via XHR), - // treat x-user-defined as windows-1252 (bug 18270) - if (source == EncodingFromMetaTag && strcasecmp(encoding.name(), "x-user-defined") == 0) - m_decoder.reset("windows-1252"); - else if (source == EncodingFromMetaTag || source == EncodingFromXMLHeader || source == EncodingFromCSSCharset) - m_decoder.reset(encoding.closest8BitEquivalent()); - else - m_decoder.reset(encoding); - - m_source = source; -} - -// Returns the position of the encoding string. -static int findXMLEncoding(const char* str, int len, int& encodingLength) -{ - int pos = find(str, len, "encoding"); - if (pos == -1) - return -1; - pos += 8; - - // Skip spaces and stray control characters. - while (pos < len && str[pos] <= ' ') - ++pos; - - // Skip equals sign. - if (pos >= len || str[pos] != '=') - return -1; - ++pos; - - // Skip spaces and stray control characters. - while (pos < len && str[pos] <= ' ') - ++pos; - - // Skip quotation mark. - if (pos >= len) - return - 1; - char quoteMark = str[pos]; - if (quoteMark != '"' && quoteMark != '\'') - return -1; - ++pos; - - // Find the trailing quotation mark. - int end = pos; - while (end < len && str[end] != quoteMark) - ++end; - if (end >= len) - return -1; - - encodingLength = end - pos; - return pos; -} - -// true if there is more to parse -static inline bool skipWhitespace(const char*& pos, const char* dataEnd) -{ - while (pos < dataEnd && (*pos == '\t' || *pos == ' ')) - ++pos; - return pos != dataEnd; -} - -void TextResourceDecoder::checkForBOM(const char* data, size_t len) -{ - // Check for UTF-16/32 or UTF-8 BOM mark at the beginning, which is a sure sign of a Unicode encoding. - - if (m_source == UserChosenEncoding) { - // FIXME: Maybe a BOM should override even a user-chosen encoding. - m_checkedForBOM = true; - return; - } - - // Check if we have enough data. - size_t bufferLength = m_buffer.size(); - if (bufferLength + len < 4) - return; - - m_checkedForBOM = true; - - // Extract the first four bytes. - // Handle the case where some of bytes are already in the buffer. - // The last byte is always guaranteed to not be in the buffer. - const unsigned char* udata = reinterpret_cast<const unsigned char*>(data); - unsigned char c1 = bufferLength >= 1 ? m_buffer[0] : *udata++; - unsigned char c2 = bufferLength >= 2 ? m_buffer[1] : *udata++; - unsigned char c3 = bufferLength >= 3 ? m_buffer[2] : *udata++; - ASSERT(bufferLength < 4); - unsigned char c4 = *udata; - - // Check for the BOM. - if (c1 == 0xFF && c2 == 0xFE) { - if (c3 !=0 || c4 != 0) - setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); - else - setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding); - } - else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) - setEncoding(UTF8Encoding(), AutoDetectedEncoding); - else if (c1 == 0xFE && c2 == 0xFF) - setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding); - else if (c1 == 0 && c2 == 0 && c3 == 0xFE && c4 == 0xFF) - setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding); -} - -bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool& movedDataToBuffer) -{ - if (m_source != DefaultEncoding) { - m_checkedForCSSCharset = true; - return true; - } - - size_t oldSize = m_buffer.size(); - m_buffer.grow(oldSize + len); - memcpy(m_buffer.data() + oldSize, data, len); - - movedDataToBuffer = true; - - if (m_buffer.size() > 8) { // strlen("@charset") == 8 - const char* dataStart = m_buffer.data(); - const char* dataEnd = dataStart + m_buffer.size(); - - if (dataStart[0] == '@' && dataStart[1] == 'c' && dataStart[2] == 'h' && dataStart[3] == 'a' && dataStart[4] == 'r' && - dataStart[5] == 's' && dataStart[6] == 'e' && dataStart[7] == 't') { - - dataStart += 8; - const char* pos = dataStart; - if (!skipWhitespace(pos, dataEnd)) - return false; - - if (*pos == '"' || *pos == '\'') { - char quotationMark = *pos; - ++pos; - dataStart = pos; - - while (pos < dataEnd && *pos != quotationMark) - ++pos; - if (pos == dataEnd) - return false; - - int encodingNameLength = pos - dataStart + 1; - - ++pos; - if (!skipWhitespace(pos, dataEnd)) - return false; - - if (*pos == ';') - setEncoding(findTextEncoding(dataStart, encodingNameLength), EncodingFromCSSCharset); - } - } - m_checkedForCSSCharset = true; - return true; - } - return false; -} - -// Other browsers allow comments in the head section, so we need to also. -// It's important not to look for tags inside the comments. -static inline void skipComment(const char*& ptr, const char* pEnd) -{ - const char* p = ptr; - // Allow <!-->; other browsers do. - if (*p == '>') { - p++; - } else { - while (p != pEnd) { - if (*p == '-') { - // This is the real end of comment, "-->". - if (p[1] == '-' && p[2] == '>') { - p += 3; - break; - } - // This is the incorrect end of comment that other browsers allow, "--!>". - if (p[1] == '-' && p[2] == '!' && p[3] == '>') { - p += 4; - break; - } - } - p++; - } - } - ptr = p; -} - -const int bytesToCheckUnconditionally = 1024; // That many input bytes will be checked for meta charset even if <head> section is over. - -bool TextResourceDecoder::checkForHeadCharset(const char* data, size_t len, bool& movedDataToBuffer) -{ - if (m_source != DefaultEncoding) { - m_checkedForHeadCharset = true; - return true; - } - - // This is not completely efficient, since the function might go - // through the HTML head several times. - - size_t oldSize = m_buffer.size(); - m_buffer.grow(oldSize + len); - memcpy(m_buffer.data() + oldSize, data, len); - - movedDataToBuffer = true; - - const char* ptr = m_buffer.data(); - const char* pEnd = ptr + m_buffer.size(); - - // Is there enough data available to check for XML declaration? - if (m_buffer.size() < 8) - return false; - - // Handle XML declaration, which can have encoding in it. This encoding is honored even for HTML documents. - // It is an error for an XML declaration not to be at the start of an XML document, and it is ignored in HTML documents in such case. - if (ptr[0] == '<' && ptr[1] == '?' && ptr[2] == 'x' && ptr[3] == 'm' && ptr[4] == 'l') { - const char* xmlDeclarationEnd = ptr; - while (xmlDeclarationEnd != pEnd && *xmlDeclarationEnd != '>') - ++xmlDeclarationEnd; - if (xmlDeclarationEnd == pEnd) - return false; - // No need for +1, because we have an extra "?" to lose at the end of XML declaration. - int len; - int pos = findXMLEncoding(ptr, xmlDeclarationEnd - ptr, len); - if (pos != -1) - setEncoding(findTextEncoding(ptr + pos, len), EncodingFromXMLHeader); - // continue looking for a charset - it may be specified in an HTTP-Equiv meta - } else if (ptr[0] == '<' && ptr[1] == 0 && ptr[2] == '?' && ptr[3] == 0 && ptr[4] == 'x' && ptr[5] == 0) { - setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); - return true; - } else if (ptr[0] == 0 && ptr[1] == '<' && ptr[2] == 0 && ptr[3] == '?' && ptr[4] == 0 && ptr[5] == 'x') { - setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding); - return true; - } else if (ptr[0] == '<' && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0 && ptr[4] == '?' && ptr[5] == 0 && ptr[6] == 0 && ptr[7] == 0) { - setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding); - return true; - } else if (ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == '<' && ptr[4] == 0 && ptr[5] == 0 && ptr[6] == 0 && ptr[7] == '?') { - setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding); - return true; - } - - // we still don't have an encoding, and are in the head - // the following tags are allowed in <head>: - // SCRIPT|STYLE|META|LINK|OBJECT|TITLE|BASE - - // We stop scanning when a tag that is not permitted in <head> - // is seen, rather when </head> is seen, because that more closely - // matches behavior in other browsers; more details in - // <http://bugs.webkit.org/show_bug.cgi?id=3590>. - - // Additionally, we ignore things that looks like tags in <title>, <script> and <noscript>; see - // <http://bugs.webkit.org/show_bug.cgi?id=4560>, <http://bugs.webkit.org/show_bug.cgi?id=12165> - // and <http://bugs.webkit.org/show_bug.cgi?id=12389>. - - // Since many sites have charset declarations after <body> or other tags that are disallowed in <head>, - // we don't bail out until we've checked at least bytesToCheckUnconditionally bytes of input. - - AtomicStringImpl* enclosingTagName = 0; - bool inHeadSection = true; // Becomes false when </head> or any tag not allowed in head is encountered. - - // the HTTP-EQUIV meta has no effect on XHTML - if (m_contentType == XML) - return true; - - while (ptr + 3 < pEnd) { // +3 guarantees that "<!--" fits in the buffer - and certainly we aren't going to lose any "charset" that way. - if (*ptr == '<') { - bool end = false; - ptr++; - - // Handle comments. - if (ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') { - ptr += 3; - skipComment(ptr, pEnd); - if (ptr - m_buffer.data() >= bytesToCheckUnconditionally && !inHeadSection) { - // Some pages that test bandwidth from within the browser do it by having - // huge comments and measuring the time they take to load. Repeatedly scanning - // these comments can take a lot of CPU time. - m_checkedForHeadCharset = true; - return true; - } - continue; - } - - if (*ptr == '/') { - ++ptr; - end = true; - } - - // Grab the tag name, but mostly ignore namespaces. - bool sawNamespace = false; - char tagBuffer[20]; - int len = 0; - while (len < 19) { - if (ptr == pEnd) - return false; - char c = *ptr; - if (c == ':') { - len = 0; - sawNamespace = true; - ptr++; - continue; - } - if (c >= 'a' && c <= 'z' || c >= '0' && c <= '9') - ; - else if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - else - break; - tagBuffer[len++] = c; - ptr++; - } - tagBuffer[len] = 0; - AtomicString tag(tagBuffer); - - if (enclosingTagName) { - if (end && tag.impl() == enclosingTagName) - enclosingTagName = 0; - } else { - if (tag == titleTag) - enclosingTagName = titleTag.localName().impl(); - else if (tag == scriptTag) - enclosingTagName = scriptTag.localName().impl(); - else if (tag == noscriptTag) - enclosingTagName = noscriptTag.localName().impl(); - } - - // Find where the opening tag ends. - const char* tagContentStart = ptr; - if (!end) { - while (ptr != pEnd && *ptr != '>') { - if (*ptr == '\'' || *ptr == '"') { - char quoteMark = *ptr; - ++ptr; - while (ptr != pEnd && *ptr != quoteMark) - ++ptr; - if (ptr == pEnd) - return false; - } - ++ptr; - } - if (ptr == pEnd) - return false; - ++ptr; - } - - if (!end && tag == metaTag && !sawNamespace) { - const char* str = tagContentStart; - int length = ptr - tagContentStart; - int pos = 0; - while (pos < length) { - int charsetPos = findIgnoringCase(str + pos, length - pos, "charset"); - if (charsetPos == -1) - break; - pos += charsetPos + 7; - // skip whitespace - while (pos < length && str[pos] <= ' ') - pos++; - if (pos == length) - break; - if (str[pos++] != '=') - continue; - while (pos < length && - (str[pos] <= ' ') || str[pos] == '=' || str[pos] == '"' || str[pos] == '\'') - pos++; - - // end ? - if (pos == length) - break; - int end = pos; - while (end < length && - str[end] != ' ' && str[end] != '"' && str[end] != '\'' && - str[end] != ';' && str[end] != '>') - end++; - setEncoding(findTextEncoding(str + pos, end - pos), EncodingFromMetaTag); - if (m_source == EncodingFromMetaTag) - return true; - - if (end >= length || str[end] == '/' || str[end] == '>') - break; - - pos = end + 1; - } - } else { - if (!enclosingTagName && tag != scriptTag && tag != noscriptTag && tag != styleTag - && tag != linkTag && tag != metaTag && tag != objectTag && tag != titleTag && tag != baseTag - && (end || tag != htmlTag) && (end || tag != headTag) && isASCIIAlpha(tagBuffer[0])) { - inHeadSection = false; - } - - if (ptr - m_buffer.data() >= bytesToCheckUnconditionally && !inHeadSection) { - m_checkedForHeadCharset = true; - return true; - } - } - } else - ++ptr; - } - return false; -} - -void TextResourceDecoder::detectJapaneseEncoding(const char* data, size_t len) -{ - switch (KanjiCode::judge(data, len)) { - case KanjiCode::JIS: - setEncoding("ISO-2022-JP", AutoDetectedEncoding); - break; - case KanjiCode::EUC: - setEncoding("EUC-JP", AutoDetectedEncoding); - break; - case KanjiCode::SJIS: - setEncoding("Shift_JIS", AutoDetectedEncoding); - break; - case KanjiCode::ASCII: - case KanjiCode::UTF16: - case KanjiCode::UTF8: - break; - } -} - -String TextResourceDecoder::decode(const char* data, size_t len) -{ - if (!m_checkedForBOM) - checkForBOM(data, len); - - bool movedDataToBuffer = false; - - if (m_contentType == CSS && !m_checkedForCSSCharset) - if (!checkForCSSCharset(data, len, movedDataToBuffer)) - return ""; - - if ((m_contentType == HTML || m_contentType == XML) && !m_checkedForHeadCharset) // HTML and XML - if (!checkForHeadCharset(data, len, movedDataToBuffer)) - return ""; - - // Do the auto-detect if our default encoding is one of the Japanese ones. - // FIXME: It seems wrong to change our encoding downstream after we have already done some decoding. - if (m_source != UserChosenEncoding && m_source != AutoDetectedEncoding && encoding().isJapanese()) - detectJapaneseEncoding(data, len); - - ASSERT(encoding().isValid()); - - if (m_buffer.isEmpty()) - return m_decoder.decode(data, len, false, m_contentType == XML, m_sawError); - - if (!movedDataToBuffer) { - size_t oldSize = m_buffer.size(); - m_buffer.grow(oldSize + len); - memcpy(m_buffer.data() + oldSize, data, len); - } - - String result = m_decoder.decode(m_buffer.data(), m_buffer.size(), false, m_contentType == XML, m_sawError); - m_buffer.clear(); - return result; -} - -String TextResourceDecoder::flush() -{ - String result = m_decoder.decode(m_buffer.data(), m_buffer.size(), true, m_contentType == XML, m_sawError); - m_buffer.clear(); - return result; -} - -} diff --git a/WebCore/loader/TextResourceDecoder.h b/WebCore/loader/TextResourceDecoder.h deleted file mode 100644 index 8bbe85e..0000000 --- a/WebCore/loader/TextResourceDecoder.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) - Copyright (C) 2006, 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. - -*/ - -#ifndef TextResourceDecoder_h -#define TextResourceDecoder_h - -#include "TextDecoder.h" - -namespace WebCore { - -class TextResourceDecoder : public RefCounted<TextResourceDecoder> { -public: - enum EncodingSource { - DefaultEncoding, - AutoDetectedEncoding, - EncodingFromXMLHeader, - EncodingFromMetaTag, - EncodingFromCSSCharset, - EncodingFromHTTPHeader, - UserChosenEncoding - }; - - static PassRefPtr<TextResourceDecoder> create(const String& mimeType, const TextEncoding& defaultEncoding = TextEncoding()) - { - return adoptRef(new TextResourceDecoder(mimeType, defaultEncoding)); - } - ~TextResourceDecoder(); - - void setEncoding(const TextEncoding&, EncodingSource); - const TextEncoding& encoding() const { return m_decoder.encoding(); } - - String decode(const char* data, size_t length); - String flush(); - - bool sawError() const { return m_sawError; } - -private: - TextResourceDecoder(const String& mimeType, const TextEncoding& defaultEncoding); - - enum ContentType { PlainText, HTML, XML, CSS }; // PlainText is equivalent to directly using TextDecoder. - static ContentType determineContentType(const String& mimeType); - static const TextEncoding& defaultEncoding(ContentType, const TextEncoding& defaultEncoding); - - void checkForBOM(const char*, size_t); - bool checkForCSSCharset(const char*, size_t, bool& movedDataToBuffer); - bool checkForHeadCharset(const char*, size_t, bool& movedDataToBuffer); - void detectJapaneseEncoding(const char*, size_t); - - ContentType m_contentType; - TextDecoder m_decoder; - EncodingSource m_source; - Vector<char> m_buffer; - bool m_checkedForBOM; - bool m_checkedForCSSCharset; - bool m_checkedForHeadCharset; - bool m_sawError; -}; - -} - -#endif diff --git a/WebCore/loader/UserStyleSheetLoader.cpp b/WebCore/loader/UserStyleSheetLoader.cpp deleted file mode 100644 index 3afbc15..0000000 --- a/WebCore/loader/UserStyleSheetLoader.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "UserStyleSheetLoader.h" - -#include "CachedCSSStyleSheet.h" -#include "DocLoader.h" -#include "Frame.h" - -using namespace WebCore; - -UserStyleSheetLoader::UserStyleSheetLoader(PassRefPtr<Document> document, const String& url) - : m_document(document) - , m_cachedSheet(m_document->docLoader()->requestUserCSSStyleSheet(url, "")) -{ - if (m_cachedSheet) { - m_document->addPendingSheet(); - m_cachedSheet->addClient(this); - } -} - -UserStyleSheetLoader::~UserStyleSheetLoader() -{ - if (m_cachedSheet) { - if (!m_cachedSheet->isLoaded()) - m_document->removePendingSheet(); - m_cachedSheet->removeClient(this); - } -} - -void UserStyleSheetLoader::setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const CachedCSSStyleSheet* sheet) -{ - m_document->removePendingSheet(); - if (Frame* frame = m_document->frame()) - frame->setUserStyleSheet(sheet->sheetText()); -} diff --git a/WebCore/loader/UserStyleSheetLoader.h b/WebCore/loader/UserStyleSheetLoader.h deleted file mode 100644 index 6e7a1ba..0000000 --- a/WebCore/loader/UserStyleSheetLoader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UserStyleSheetLoader_h -#define UserStyleSheetLoader_h - -#include "CachedResourceClient.h" -#include "CachedResourceHandle.h" - -#include "Document.h" - -namespace WebCore { - class CachedCSSStyleSheet; - class String; - - // This class is deprecated and should not be used in any new code. User - // stylesheet loading should instead happen through Page. - class UserStyleSheetLoader : CachedResourceClient { - public: - UserStyleSheetLoader(PassRefPtr<Document>, const String& url); - ~UserStyleSheetLoader(); - - private: - virtual void setCSSStyleSheet(const String& URL, const String& charset, const CachedCSSStyleSheet* sheet); - - RefPtr<Document> m_document; - CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet; - }; - -} // namespace WebCore - -#endif // UserStyleSheetLoader_h diff --git a/WebCore/loader/appcache/ApplicationCache.cpp b/WebCore/loader/appcache/ApplicationCache.cpp deleted file mode 100644 index d29eda8..0000000 --- a/WebCore/loader/appcache/ApplicationCache.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ApplicationCache.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCacheGroup.h" -#include "ApplicationCacheResource.h" -#include "ApplicationCacheStorage.h" -#include "ResourceRequest.h" -#include <stdio.h> - -namespace WebCore { - -ApplicationCache::ApplicationCache() - : m_group(0) - , m_manifest(0) - , m_storageID(0) -{ -} - -ApplicationCache::~ApplicationCache() -{ - if (m_group && !m_group->isCopy()) - m_group->cacheDestroyed(this); -} - -void ApplicationCache::setGroup(ApplicationCacheGroup* group) -{ - ASSERT(!m_group); - m_group = group; -} - -void ApplicationCache::setManifestResource(PassRefPtr<ApplicationCacheResource> manifest) -{ - ASSERT(manifest); - ASSERT(!m_manifest); - ASSERT(manifest->type() & ApplicationCacheResource::Manifest); - - m_manifest = manifest.get(); - - addResource(manifest); -} - -void ApplicationCache::addResource(PassRefPtr<ApplicationCacheResource> resource) -{ - ASSERT(resource); - - const String& url = resource->url(); - - ASSERT(!m_resources.contains(url)); - - if (m_storageID) { - ASSERT(!resource->storageID()); - - // Add the resource to the storage. - cacheStorage().store(resource.get(), this); - } - - m_resources.set(url, resource); -} - -unsigned ApplicationCache::removeResource(const String& url) -{ - HashMap<String, RefPtr<ApplicationCacheResource> >::iterator it = m_resources.find(url); - if (it == m_resources.end()) - return 0; - - // The resource exists, get its type so we can return it. - unsigned type = it->second->type(); - - m_resources.remove(it); - - return type; -} - -ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url) -{ - return m_resources.get(url).get(); -} - -bool ApplicationCache::requestIsHTTPOrHTTPSGet(const ResourceRequest& request) -{ - if (!request.url().protocolIs("http") && !request.url().protocolIs("https")) - return false; - - if (!equalIgnoringCase(request.httpMethod(), "GET")) - return false; - - return true; -} - -ApplicationCacheResource* ApplicationCache::resourceForRequest(const ResourceRequest& request) -{ - // We only care about HTTP/HTTPS GET requests. - if (!requestIsHTTPOrHTTPSGet(request)) - return false; - - return resourceForURL(request.url()); -} - -unsigned ApplicationCache::numDynamicEntries() const -{ - // FIXME: Implement - return 0; -} - -String ApplicationCache::dynamicEntry(unsigned index) const -{ - // FIXME: Implement - return String(); -} - -bool ApplicationCache::addDynamicEntry(const String& url) -{ - if (!equalIgnoringCase(m_group->manifestURL().protocol(), - KURL(url).protocol())) - return false; - - // FIXME: Implement - return true; -} - -void ApplicationCache::removeDynamicEntry(const String& url) -{ - // FIXME: Implement -} - -void ApplicationCache::setOnlineWhitelist(const HashSet<String>& onlineWhitelist) -{ - ASSERT(m_onlineWhitelist.isEmpty()); - m_onlineWhitelist = onlineWhitelist; -} - -bool ApplicationCache::isURLInOnlineWhitelist(const KURL& url) -{ - if (!url.hasRef()) - return m_onlineWhitelist.contains(url); - - KURL copy(url); - copy.setRef(String()); - return m_onlineWhitelist.contains(copy); -} - -void ApplicationCache::clearStorageID() -{ - m_storageID = 0; - - ResourceMap::const_iterator end = m_resources.end(); - for (ResourceMap::const_iterator it = m_resources.begin(); it != end; ++it) - it->second->clearStorageID(); -} - -#ifndef NDEBUG -void ApplicationCache::dump() -{ - HashMap<String, RefPtr<ApplicationCacheResource> >::const_iterator end = m_resources.end(); - - for (HashMap<String, RefPtr<ApplicationCacheResource> >::const_iterator it = m_resources.begin(); it != end; ++it) { - printf("%s ", it->first.ascii().data()); - ApplicationCacheResource::dumpType(it->second->type()); - } -} -#endif - -} - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ApplicationCache.h b/WebCore/loader/appcache/ApplicationCache.h deleted file mode 100644 index e536cbe..0000000 --- a/WebCore/loader/appcache/ApplicationCache.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ApplicationCache_h -#define ApplicationCache_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - -#include "StringHash.h" -#include "PlatformString.h" - -namespace WebCore { - -class ApplicationCacheGroup; -class ApplicationCacheResource; -class DocumentLoader; -class KURL; -class ResourceRequest; - -class ApplicationCache : public RefCounted<ApplicationCache> { -public: - static PassRefPtr<ApplicationCache> create() { return adoptRef(new ApplicationCache); } - ~ApplicationCache(); - - void addResource(PassRefPtr<ApplicationCacheResource> resource); - unsigned removeResource(const String& url); - - void setManifestResource(PassRefPtr<ApplicationCacheResource> manifest); - ApplicationCacheResource* manifestResource() const { return m_manifest; } - - void setGroup(ApplicationCacheGroup*); - ApplicationCacheGroup* group() const { return m_group; } - - ApplicationCacheResource* resourceForRequest(const ResourceRequest&); - ApplicationCacheResource* resourceForURL(const String& url); - - unsigned numDynamicEntries() const; - String dynamicEntry(unsigned index) const; - - bool addDynamicEntry(const String& url); - void removeDynamicEntry(const String& url); - - void setOnlineWhitelist(const HashSet<String>& onlineWhitelist); - const HashSet<String>& onlineWhitelist() const { return m_onlineWhitelist; } - bool isURLInOnlineWhitelist(const KURL&); - -#ifndef NDEBUG - void dump(); -#endif - - typedef HashMap<String, RefPtr<ApplicationCacheResource> > ResourceMap; - ResourceMap::const_iterator begin() const { return m_resources.begin(); } - ResourceMap::const_iterator end() const { return m_resources.end(); } - - void setStorageID(unsigned storageID) { m_storageID = storageID; } - unsigned storageID() const { return m_storageID; } - void clearStorageID(); - - static bool requestIsHTTPOrHTTPSGet(const ResourceRequest&); -private: - ApplicationCache(); - - ApplicationCacheGroup* m_group; - ResourceMap m_resources; - ApplicationCacheResource* m_manifest; - - HashSet<String> m_onlineWhitelist; - - unsigned m_storageID; -}; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ApplicationCache_h diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.cpp b/WebCore/loader/appcache/ApplicationCacheGroup.cpp deleted file mode 100644 index ff26767..0000000 --- a/WebCore/loader/appcache/ApplicationCacheGroup.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ApplicationCacheGroup.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCache.h" -#include "ApplicationCacheResource.h" -#include "ApplicationCacheStorage.h" -#include "DocumentLoader.h" -#include "DOMApplicationCache.h" -#include "DOMWindow.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "MainResourceLoader.h" -#include "ManifestParser.h" -#include "Page.h" -#include "Settings.h" -#include <wtf/HashMap.h> - -namespace WebCore { - -ApplicationCacheGroup::ApplicationCacheGroup(const KURL& manifestURL, bool isCopy) - : m_manifestURL(manifestURL) - , m_status(Idle) - , m_savedNewestCachePointer(0) - , m_frame(0) - , m_storageID(0) - , m_isCopy(isCopy) -{ -} - -ApplicationCacheGroup::~ApplicationCacheGroup() -{ - if (m_isCopy) { - ASSERT(m_newestCache); - ASSERT(m_caches.size() == 1); - ASSERT(m_caches.contains(m_newestCache.get())); - ASSERT(!m_cacheBeingUpdated); - ASSERT(m_associatedDocumentLoaders.isEmpty()); - ASSERT(m_cacheCandidates.isEmpty()); - ASSERT(m_newestCache->group() == this); - - return; - } - - ASSERT(!m_newestCache); - ASSERT(m_caches.isEmpty()); - - stopLoading(); - - cacheStorage().cacheGroupDestroyed(this); -} - -ApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceRequest& request, DocumentLoader* loader) -{ - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) - return 0; - - ASSERT(loader->frame()); - ASSERT(loader->frame()->page()); - if (loader->frame() != loader->frame()->page()->mainFrame()) - return 0; - - if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(request.url())) { - ASSERT(group->newestCache()); - - return group->newestCache(); - } - - return 0; -} - -void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL) -{ - ASSERT(frame && frame->page()); - - if (!frame->settings()->offlineWebApplicationCacheEnabled()) - return; - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - ASSERT(!documentLoader->applicationCache()); - - if (manifestURL.isNull()) { - selectCacheWithoutManifestURL(frame); - return; - } - - ApplicationCache* mainResourceCache = documentLoader->mainResourceApplicationCache(); - - // Check if the main resource is being loaded as part of navigation of the main frame - bool isMainFrame = frame->page()->mainFrame() == frame; - - if (!isMainFrame) { - if (mainResourceCache && manifestURL != mainResourceCache->group()->manifestURL()) { - ApplicationCacheResource* resource = mainResourceCache->resourceForURL(documentLoader->originalURL()); - ASSERT(resource); - - resource->addType(ApplicationCacheResource::Foreign); - } - - return; - } - - if (mainResourceCache) { - if (manifestURL == mainResourceCache->group()->m_manifestURL) { - mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache); - mainResourceCache->group()->update(frame); - } else { - // FIXME: If the resource being loaded was loaded from an application cache and the URI of - // that application cache's manifest is not the same as the manifest URI with which the algorithm was invoked - // then we should "undo" the navigation. - } - - return; - } - - // The resource was loaded from the network, check if it is a HTTP/HTTPS GET. - const ResourceRequest& request = frame->loader()->activeDocumentLoader()->request(); - - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) { - selectCacheWithoutManifestURL(frame); - return; - } - - // Check that the resource URL has the same scheme/host/port as the manifest URL. - if (!protocolHostAndPortAreEqual(manifestURL, request.url())) { - selectCacheWithoutManifestURL(frame); - return; - } - - ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL); - - if (ApplicationCache* cache = group->newestCache()) { - ASSERT(cache->manifestResource()); - - group->associateDocumentLoaderWithCache(frame->loader()->documentLoader(), cache); - - if (!frame->loader()->documentLoader()->isLoadingMainResource()) - group->finishedLoadingMainResource(frame->loader()->documentLoader()); - - group->update(frame); - } else { - bool isUpdating = group->m_cacheBeingUpdated; - - if (!isUpdating) - group->m_cacheBeingUpdated = ApplicationCache::create(); - documentLoader->setCandidateApplicationCacheGroup(group); - group->m_cacheCandidates.add(documentLoader); - - const KURL& url = frame->loader()->documentLoader()->originalURL(); - - unsigned type = 0; - - // If the resource has already been downloaded, remove it so that it will be replaced with the implicit resource - if (isUpdating) - type = group->m_cacheBeingUpdated->removeResource(url); - - // Add the main resource URL as an implicit entry. - group->addEntry(url, type | ApplicationCacheResource::Implicit); - - if (!frame->loader()->documentLoader()->isLoadingMainResource()) - group->finishedLoadingMainResource(frame->loader()->documentLoader()); - - if (!isUpdating) - group->update(frame); - } -} - -void ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame* frame) -{ - if (!frame->settings()->offlineWebApplicationCacheEnabled()) - return; - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - ASSERT(!documentLoader->applicationCache()); - - ApplicationCache* mainResourceCache = documentLoader->mainResourceApplicationCache(); - bool isMainFrame = frame->page()->mainFrame() == frame; - - if (isMainFrame && mainResourceCache) { - mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache); - mainResourceCache->group()->update(frame); - } -} - -void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader) -{ - const KURL& url = loader->originalURL(); - - if (ApplicationCache* cache = loader->applicationCache()) { - RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Implicit, loader->mainResourceData()); - cache->addResource(resource.release()); - - if (!m_cacheBeingUpdated) - return; - } - - ASSERT(m_pendingEntries.contains(url)); - - EntryMap::iterator it = m_pendingEntries.find(url); - ASSERT(it->second & ApplicationCacheResource::Implicit); - - RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, loader->response(), it->second, loader->mainResourceData()); - - ASSERT(m_cacheBeingUpdated); - m_cacheBeingUpdated->addResource(resource.release()); - - m_pendingEntries.remove(it); - - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader* loader) -{ - ASSERT(m_cacheCandidates.contains(loader) || m_associatedDocumentLoaders.contains(loader)); - - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); -} - -void ApplicationCacheGroup::stopLoading() -{ - if (m_manifestHandle) { - ASSERT(!m_currentHandle); - ASSERT(!m_cacheBeingUpdated); - - m_manifestHandle->setClient(0); - m_manifestHandle->cancel(); - m_manifestHandle = 0; - } - - if (m_currentHandle) { - ASSERT(!m_manifestHandle); - ASSERT(m_cacheBeingUpdated); - - m_currentHandle->setClient(0); - m_currentHandle->cancel(); - m_currentHandle = 0; - } - - m_cacheBeingUpdated = 0; -} - -void ApplicationCacheGroup::documentLoaderDestroyed(DocumentLoader* loader) -{ - HashSet<DocumentLoader*>::iterator it = m_associatedDocumentLoaders.find(loader); - - if (it != m_associatedDocumentLoaders.end()) { - ASSERT(!m_cacheCandidates.contains(loader)); - - m_associatedDocumentLoaders.remove(it); - } else { - ASSERT(m_cacheCandidates.contains(loader)); - m_cacheCandidates.remove(loader); - } - - if (!m_associatedDocumentLoaders.isEmpty() || !m_cacheCandidates.isEmpty()) - return; - - // We should only have the newest cache remaining, or there is an initial cache attempt in progress. - ASSERT(m_caches.size() == 1 || m_cacheBeingUpdated); - - // If a cache update is in progress, stop it. - if (m_caches.size() == 1) { - ASSERT(m_caches.contains(m_newestCache.get())); - - // Release our reference to the newest cache. - m_savedNewestCachePointer = m_newestCache.get(); - - // This could cause us to be deleted. - m_newestCache = 0; - - return; - } - - // There is an initial cache attempt in progress - ASSERT(m_cacheBeingUpdated); - ASSERT(m_caches.size() == 0); - - // Delete ourselves, causing the cache attempt to be stopped. - delete this; -} - -void ApplicationCacheGroup::cacheDestroyed(ApplicationCache* cache) -{ - ASSERT(m_caches.contains(cache)); - - m_caches.remove(cache); - - if (cache != m_savedNewestCachePointer) - cacheStorage().remove(cache); - - if (m_caches.isEmpty()) - delete this; -} - -void ApplicationCacheGroup::setNewestCache(PassRefPtr<ApplicationCache> newestCache) -{ - ASSERT(!m_newestCache); - ASSERT(!m_caches.contains(newestCache.get())); - ASSERT(!newestCache->group()); - - m_newestCache = newestCache; - m_caches.add(m_newestCache.get()); - m_newestCache->setGroup(this); -} - -void ApplicationCacheGroup::update(Frame* frame) -{ - if (m_status == Checking || m_status == Downloading) - return; - - ASSERT(!m_frame); - m_frame = frame; - - m_status = Checking; - - callListenersOnAssociatedDocuments(&DOMApplicationCache::callCheckingListener); - - ASSERT(!m_manifestHandle); - ASSERT(!m_manifestResource); - - // FIXME: Handle defer loading - - ResourceRequest request(m_manifestURL); - m_frame->loader()->applyUserAgent(request); - - m_manifestHandle = ResourceHandle::create(request, this, m_frame, false, true, false); -} - -void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response) -{ - if (handle == m_manifestHandle) { - didReceiveManifestResponse(response); - return; - } - - ASSERT(handle == m_currentHandle); - - int statusCode = response.httpStatusCode() / 100; - if (statusCode == 4 || statusCode == 5) { - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); - return; - } - - const KURL& url = handle->request().url(); - - ASSERT(!m_currentResource); - ASSERT(m_pendingEntries.contains(url)); - - unsigned type = m_pendingEntries.get(url); - - // If this is an initial cache attempt, we should not get implicit resources delivered here. - if (!m_newestCache) - ASSERT(!(type & ApplicationCacheResource::Implicit)); - - m_currentResource = ApplicationCacheResource::create(url, response, type); -} - -void ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived) -{ - if (handle == m_manifestHandle) { - didReceiveManifestData(data, length); - return; - } - - ASSERT(handle == m_currentHandle); - - ASSERT(m_currentResource); - m_currentResource->data()->append(data, length); -} - -void ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle) -{ - if (handle == m_manifestHandle) { - didFinishLoadingManifest(); - return; - } - - ASSERT(m_currentHandle == handle); - ASSERT(m_pendingEntries.contains(handle->request().url())); - - m_pendingEntries.remove(handle->request().url()); - - ASSERT(m_cacheBeingUpdated); - - m_cacheBeingUpdated->addResource(m_currentResource.release()); - m_currentHandle = 0; - - // Load the next file. - if (!m_pendingEntries.isEmpty()) { - startLoadingEntry(); - return; - } - - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError&) -{ - if (handle == m_manifestHandle) { - didFailToLoadManifest(); - return; - } - - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); -} - -void ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& response) -{ - int statusCode = response.httpStatusCode() / 100; - - if (statusCode == 4 || statusCode == 5 || - !equalIgnoringCase(response.mimeType(), "text/cache-manifest")) { - didFailToLoadManifest(); - return; - } - - ASSERT(!m_manifestResource); - ASSERT(m_manifestHandle); - m_manifestResource = ApplicationCacheResource::create(m_manifestHandle->request().url(), response, - ApplicationCacheResource::Manifest); -} - -void ApplicationCacheGroup::didReceiveManifestData(const char* data, int length) -{ - ASSERT(m_manifestResource); - m_manifestResource->data()->append(data, length); -} - -void ApplicationCacheGroup::didFinishLoadingManifest() -{ - if (!m_manifestResource) { - didFailToLoadManifest(); - return; - } - - bool isUpgradeAttempt = m_newestCache; - - m_manifestHandle = 0; - - // Check if the manifest is byte-for-byte identical. - if (isUpgradeAttempt) { - ApplicationCacheResource* newestManifest = m_newestCache->manifestResource(); - ASSERT(newestManifest); - - if (newestManifest->data()->size() == m_manifestResource->data()->size() && - !memcmp(newestManifest->data()->data(), m_manifestResource->data()->data(), newestManifest->data()->size())) { - - callListenersOnAssociatedDocuments(&DOMApplicationCache::callNoUpdateListener); - - m_status = Idle; - m_frame = 0; - m_manifestResource = 0; - return; - } - } - - Manifest manifest; - if (!parseManifest(m_manifestURL, m_manifestResource->data()->data(), m_manifestResource->data()->size(), manifest)) { - didFailToLoadManifest(); - return; - } - - // FIXME: Add the opportunistic caching namespaces and their fallbacks. - - // We have the manifest, now download the resources. - m_status = Downloading; - - callListenersOnAssociatedDocuments(&DOMApplicationCache::callDownloadingListener); - -#ifndef NDEBUG - // We should only have implicit entries. - { - EntryMap::const_iterator end = m_pendingEntries.end(); - for (EntryMap::const_iterator it = m_pendingEntries.begin(); it != end; ++it) - ASSERT(it->second & ApplicationCacheResource::Implicit); - } -#endif - - if (isUpgradeAttempt) { - ASSERT(!m_cacheBeingUpdated); - - m_cacheBeingUpdated = ApplicationCache::create(); - - ApplicationCache::ResourceMap::const_iterator end = m_newestCache->end(); - for (ApplicationCache::ResourceMap::const_iterator it = m_newestCache->begin(); it != end; ++it) { - unsigned type = it->second->type(); - if (type & (ApplicationCacheResource::Opportunistic | ApplicationCacheResource::Implicit | ApplicationCacheResource::Dynamic)) - addEntry(it->first, type); - } - } - - HashSet<String>::const_iterator end = manifest.explicitURLs.end(); - for (HashSet<String>::const_iterator it = manifest.explicitURLs.begin(); it != end; ++it) - addEntry(*it, ApplicationCacheResource::Explicit); - - m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs); - - startLoadingEntry(); -} - -void ApplicationCacheGroup::cacheUpdateFailed() -{ - stopLoading(); - - callListenersOnAssociatedDocuments(&DOMApplicationCache::callErrorListener); - - m_pendingEntries.clear(); - m_manifestResource = 0; - - while (!m_cacheCandidates.isEmpty()) { - HashSet<DocumentLoader*>::iterator it = m_cacheCandidates.begin(); - - ASSERT((*it)->candidateApplicationCacheGroup() == this); - (*it)->setCandidateApplicationCacheGroup(0); - m_cacheCandidates.remove(it); - } - - m_status = Idle; - m_frame = 0; - - // If there are no associated caches, delete ourselves - if (m_associatedDocumentLoaders.isEmpty()) - delete this; -} - - -void ApplicationCacheGroup::didFailToLoadManifest() -{ - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); -} - -void ApplicationCacheGroup::checkIfLoadIsComplete() -{ - ASSERT(m_cacheBeingUpdated); - - if (m_manifestHandle) - return; - - if (!m_pendingEntries.isEmpty()) - return; - - // We're done - bool isUpgradeAttempt = m_newestCache; - - m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); - - m_status = Idle; - m_frame = 0; - - Vector<RefPtr<DocumentLoader> > documentLoaders; - - if (isUpgradeAttempt) { - ASSERT(m_cacheCandidates.isEmpty()); - - copyToVector(m_associatedDocumentLoaders, documentLoaders); - } else { - while (!m_cacheCandidates.isEmpty()) { - HashSet<DocumentLoader*>::iterator it = m_cacheCandidates.begin(); - - DocumentLoader* loader = *it; - ASSERT(!loader->applicationCache()); - ASSERT(loader->candidateApplicationCacheGroup() == this); - - associateDocumentLoaderWithCache(loader, m_cacheBeingUpdated.get()); - - documentLoaders.append(loader); - - m_cacheCandidates.remove(it); - } - } - - setNewestCache(m_cacheBeingUpdated.release()); - - // Store the cache - cacheStorage().storeNewestCache(this); - - callListeners(isUpgradeAttempt ? &DOMApplicationCache::callUpdateReadyListener : &DOMApplicationCache::callCachedListener, - documentLoaders); -} - -void ApplicationCacheGroup::startLoadingEntry() -{ - ASSERT(m_cacheBeingUpdated); - - if (m_pendingEntries.isEmpty()) { - checkIfLoadIsComplete(); - return; - } - - EntryMap::const_iterator it = m_pendingEntries.begin(); - - // If this is an initial cache attempt, we do not want to fetch any implicit entries, - // since those are fed to us by the normal loader machinery. - if (!m_newestCache) { - // Get the first URL in the entry table that is not implicit - EntryMap::const_iterator end = m_pendingEntries.end(); - - while (it->second & ApplicationCacheResource::Implicit) { - ++it; - - if (it == end) - return; - } - } - - callListenersOnAssociatedDocuments(&DOMApplicationCache::callProgressListener); - - // FIXME: If this is an upgrade attempt, the newest cache should be used as an HTTP cache. - - ASSERT(!m_currentHandle); - - ResourceRequest request(it->first); - m_frame->loader()->applyUserAgent(request); - - m_currentHandle = ResourceHandle::create(request, this, m_frame, false, true, false); -} - -void ApplicationCacheGroup::addEntry(const String& url, unsigned type) -{ - ASSERT(m_cacheBeingUpdated); - - // Don't add the URL if we already have an implicit resource in the cache - if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) { - ASSERT(resource->type() & ApplicationCacheResource::Implicit); - - resource->addType(type); - return; - } - - // Don't add the URL if it's the same as the manifest URL. - if (m_manifestResource && m_manifestResource->url() == url) { - m_manifestResource->addType(type); - return; - } - - pair<EntryMap::iterator, bool> result = m_pendingEntries.add(url, type); - - if (!result.second) - result.first->second |= type; -} - -void ApplicationCacheGroup::associateDocumentLoaderWithCache(DocumentLoader* loader, ApplicationCache* cache) -{ - loader->setApplicationCache(cache); - - ASSERT(!m_associatedDocumentLoaders.contains(loader)); - m_associatedDocumentLoaders.add(loader); -} - -void ApplicationCacheGroup::callListenersOnAssociatedDocuments(ListenerFunction listenerFunction) -{ - Vector<RefPtr<DocumentLoader> > loaders; - copyToVector(m_associatedDocumentLoaders, loaders); - - callListeners(listenerFunction, loaders); -} - -void ApplicationCacheGroup::callListeners(ListenerFunction listenerFunction, const Vector<RefPtr<DocumentLoader> >& loaders) -{ - for (unsigned i = 0; i < loaders.size(); i++) { - Frame* frame = loaders[i]->frame(); - if (!frame) - continue; - - ASSERT(frame->loader()->documentLoader() == loaders[i]); - DOMWindow* window = frame->domWindow(); - - if (DOMApplicationCache* domCache = window->optionalApplicationCache()) - (domCache->*listenerFunction)(); - } -} - -void ApplicationCacheGroup::clearStorageID() -{ - m_storageID = 0; - - HashSet<ApplicationCache*>::const_iterator end = m_caches.end(); - for (HashSet<ApplicationCache*>::const_iterator it = m_caches.begin(); it != end; ++it) - (*it)->clearStorageID(); -} - - -} - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.h b/WebCore/loader/appcache/ApplicationCacheGroup.h deleted file mode 100644 index d5b7563..0000000 --- a/WebCore/loader/appcache/ApplicationCacheGroup.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ApplicationCacheGroup_h -#define ApplicationCacheGroup_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include <wtf/Noncopyable.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> - -#include "KURL.h" -#include "PlatformString.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "SharedBuffer.h" - -namespace WebCore { - -class ApplicationCache; -class ApplicationCacheResource; -class DOMApplicationCache; -class Document; -class DocumentLoader; -class Frame; - -class ApplicationCacheGroup : Noncopyable, ResourceHandleClient { -public: - ApplicationCacheGroup(const KURL& manifestURL, bool isCopy = false); - ~ApplicationCacheGroup(); - - enum Status { Idle, Checking, Downloading }; - - static ApplicationCache* cacheForMainRequest(const ResourceRequest&, DocumentLoader*); - - static void selectCache(Frame*, const KURL& manifestURL); - static void selectCacheWithoutManifestURL(Frame*); - - const KURL& manifestURL() const { return m_manifestURL; } - Status status() const { return m_status; } - - void setStorageID(unsigned storageID) { m_storageID = storageID; } - unsigned storageID() const { return m_storageID; } - void clearStorageID(); - - void update(Frame*); - void cacheDestroyed(ApplicationCache*); - - ApplicationCache* newestCache() const { return m_newestCache.get(); } - ApplicationCache* savedNewestCachePointer() const { return m_savedNewestCachePointer; } - - void finishedLoadingMainResource(DocumentLoader*); - void failedLoadingMainResource(DocumentLoader*); - void documentLoaderDestroyed(DocumentLoader*); - - void setNewestCache(PassRefPtr<ApplicationCache> newestCache); - - bool isCopy() const { return m_isCopy; } -private: - typedef void (DOMApplicationCache::*ListenerFunction)(); - void callListenersOnAssociatedDocuments(ListenerFunction); - void callListeners(ListenerFunction, const Vector<RefPtr<DocumentLoader> >& loaders); - - virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); - virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived); - virtual void didFinishLoading(ResourceHandle*); - virtual void didFail(ResourceHandle*, const ResourceError&); - - void didReceiveManifestResponse(const ResourceResponse&); - void didReceiveManifestData(const char*, int); - void didFinishLoadingManifest(); - void didFailToLoadManifest(); - - void startLoadingEntry(); - void checkIfLoadIsComplete(); - void cacheUpdateFailed(); - - void addEntry(const String&, unsigned type); - - void associateDocumentLoaderWithCache(DocumentLoader*, ApplicationCache*); - - void stopLoading(); - - KURL m_manifestURL; - Status m_status; - - // This is the newest cache in the group. - RefPtr<ApplicationCache> m_newestCache; - - // During tear-down we save the pointer to the newest cache to prevent reference cycles. - ApplicationCache* m_savedNewestCachePointer; - - // The caches in this cache group. - HashSet<ApplicationCache*> m_caches; - - // The cache being updated (if any). - RefPtr<ApplicationCache> m_cacheBeingUpdated; - - // When a cache group does not yet have a complete cache, this contains the document loaders - // that should be associated with the cache once it has been downloaded. - HashSet<DocumentLoader*> m_cacheCandidates; - - // These are all the document loaders that are associated with a cache in this group. - HashSet<DocumentLoader*> m_associatedDocumentLoaders; - - // The URLs and types of pending cache entries. - typedef HashMap<String, unsigned> EntryMap; - EntryMap m_pendingEntries; - - // Frame used for fetching resources when updating - Frame* m_frame; - - unsigned m_storageID; - - // Whether this cache group is a copy that's only used for transferring the cache to another file. - bool m_isCopy; - - RefPtr<ResourceHandle> m_currentHandle; - RefPtr<ApplicationCacheResource> m_currentResource; - - RefPtr<ApplicationCacheResource> m_manifestResource; - RefPtr<ResourceHandle> m_manifestHandle; -}; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ApplicationCacheGroup_h diff --git a/WebCore/loader/appcache/ApplicationCacheResource.cpp b/WebCore/loader/appcache/ApplicationCacheResource.cpp deleted file mode 100644 index ee82ff5..0000000 --- a/WebCore/loader/appcache/ApplicationCacheResource.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ApplicationCacheResource.h" -#include <stdio.h> - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -namespace WebCore { - -ApplicationCacheResource::ApplicationCacheResource(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> data) - : SubstituteResource(url, response, data) - , m_type(type) - , m_storageID(0) -{ -} - -void ApplicationCacheResource::addType(unsigned type) -{ - ASSERT(!m_storageID); - m_type |= type; -} - -#ifndef NDEBUG -void ApplicationCacheResource::dumpType(unsigned type) -{ - if (type & Implicit) - printf("implicit "); - if (type & Manifest) - printf("manifest "); - if (type & Explicit) - printf("explicit "); - if (type & Foreign) - printf("foreign "); - if (type & Fallback) - printf("fallback "); - if (type & Opportunistic) - printf("opportunistic "); - if (type & Dynamic) - printf("dynamic "); - - printf("\n"); -} -#endif - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ApplicationCacheResource.h b/WebCore/loader/appcache/ApplicationCacheResource.h deleted file mode 100644 index 1d7b853..0000000 --- a/WebCore/loader/appcache/ApplicationCacheResource.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ApplicationCacheResource_h -#define ApplicationCacheResource_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "SubstituteResource.h" - -namespace WebCore { - -class ApplicationCacheResource : public SubstituteResource { -public: - enum Type { - Implicit = 1 << 0, - Manifest = 1 << 1, - Explicit = 1 << 2, - Foreign = 1 << 3, - Fallback = 1 << 4, - Opportunistic = 1 << 5, - Dynamic = 1 << 6 - }; - - static PassRefPtr<ApplicationCacheResource> create(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer = SharedBuffer::create()) - { - return adoptRef(new ApplicationCacheResource(url, response, type, buffer)); - } - - unsigned type() const { return m_type; } - void addType(unsigned type); - - void setStorageID(unsigned storageID) { m_storageID = storageID; } - unsigned storageID() const { return m_storageID; } - void clearStorageID() { m_storageID = 0; } - -#ifndef NDEBUG - static void dumpType(unsigned type); -#endif - -private: - ApplicationCacheResource(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer); - - unsigned m_type; - unsigned m_storageID; -}; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ApplicationCacheResource_h diff --git a/WebCore/loader/appcache/ApplicationCacheStorage.cpp b/WebCore/loader/appcache/ApplicationCacheStorage.cpp deleted file mode 100644 index 910d00c..0000000 --- a/WebCore/loader/appcache/ApplicationCacheStorage.cpp +++ /dev/null @@ -1,663 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ApplicationCacheStorage.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCache.h" -#include "ApplicationCacheGroup.h" -#include "ApplicationCacheResource.h" -#include "FileSystem.h" -#include "CString.h" -#include "KURL.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" - -namespace WebCore { - -static unsigned urlHostHash(const KURL& url) -{ - unsigned hostStart = url.hostStart(); - unsigned hostEnd = url.hostEnd(); - - return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url.string().characters() + hostStart, hostEnd - hostStart)); -} - -ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const KURL& manifestURL) -{ - openDatabase(false); - if (!m_database.isOpen()) - return 0; - - SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL AND manifestURL=?"); - if (statement.prepare() != SQLResultOk) - return 0; - - statement.bindText(1, manifestURL); - - int result = statement.step(); - if (result == SQLResultDone) - return 0; - - if (result != SQLResultRow) { - LOG_ERROR("Could not load cache group, error \"%s\"", m_database.lastErrorMsg()); - return 0; - } - - unsigned newestCacheStorageID = (unsigned)statement.getColumnInt64(2); - - RefPtr<ApplicationCache> cache = loadCache(newestCacheStorageID); - if (!cache) - return 0; - - ApplicationCacheGroup* group = new ApplicationCacheGroup(manifestURL); - - group->setStorageID((unsigned)statement.getColumnInt64(0)); - group->setNewestCache(cache.release()); - - return group; -} - -ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const KURL& manifestURL) -{ - std::pair<CacheGroupMap::iterator, bool> result = m_cachesInMemory.add(manifestURL, 0); - - if (!result.second) { - ASSERT(result.first->second); - - return result.first->second; - } - - // Look up the group in the database - ApplicationCacheGroup* group = loadCacheGroup(manifestURL); - - // If the group was not found we need to create it - if (!group) { - group = new ApplicationCacheGroup(manifestURL); - m_cacheHostSet.add(urlHostHash(manifestURL)); - } - - result.first->second = group; - - return group; -} - -void ApplicationCacheStorage::loadManifestHostHashes() -{ - static bool hasLoadedHashes = false; - - if (hasLoadedHashes) - return; - - // We set this flag to true before the database has been opened - // to avoid trying to open the database over and over if it doesn't exist. - hasLoadedHashes = true; - - openDatabase(false); - if (!m_database.isOpen()) - return; - - // Fetch the host hashes. - SQLiteStatement statement(m_database, "SELECT manifestHostHash FROM CacheGroups"); - if (statement.prepare() != SQLResultOk) - return; - - int result; - while ((result = statement.step()) == SQLResultRow) - m_cacheHostSet.add((unsigned)statement.getColumnInt64(0)); -} - -ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url) -{ - loadManifestHostHashes(); - - // Hash the host name and see if there's a manifest with the same host. - if (!m_cacheHostSet.contains(urlHostHash(url))) - return 0; - - // Check if a cache already exists in memory. - CacheGroupMap::const_iterator end = m_cachesInMemory.end(); - for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) { - ApplicationCacheGroup* group = it->second; - - if (!protocolHostAndPortAreEqual(url, group->manifestURL())) - continue; - - if (ApplicationCache* cache = group->newestCache()) { - if (cache->resourceForURL(url)) - return group; - } - } - - if (!m_database.isOpen()) - return 0; - - // Check the database. Look for all cache groups with a newest cache. - SQLiteStatement statement(m_database, "SELECT id, manifestURL, newestCache FROM CacheGroups WHERE newestCache IS NOT NULL"); - if (statement.prepare() != SQLResultOk) - return 0; - - int result; - while ((result = statement.step()) == SQLResultRow) { - KURL manifestURL = KURL(statement.getColumnText(1)); - - if (!protocolHostAndPortAreEqual(url, manifestURL)) - continue; - - // We found a cache group that matches. Now check if the newest cache has a resource with - // a matching URL. - unsigned newestCacheID = (unsigned)statement.getColumnInt64(2); - RefPtr<ApplicationCache> cache = loadCache(newestCacheID); - - if (!cache->resourceForURL(url)) - continue; - - ApplicationCacheGroup* group = new ApplicationCacheGroup(manifestURL); - - group->setStorageID((unsigned)statement.getColumnInt64(0)); - group->setNewestCache(cache.release()); - - ASSERT(!m_cachesInMemory.contains(manifestURL)); - m_cachesInMemory.set(group->manifestURL(), group); - - return group; - } - - if (result != SQLResultDone) - LOG_ERROR("Could not load cache group, error \"%s\"", m_database.lastErrorMsg()); - - return 0; -} - -void ApplicationCacheStorage::cacheGroupDestroyed(ApplicationCacheGroup* group) -{ - ASSERT(m_cachesInMemory.get(group->manifestURL()) == group); - - m_cachesInMemory.remove(group->manifestURL()); - - // If the cache is half-created, we don't want it in the saved set. - if (!group->savedNewestCachePointer()) - m_cacheHostSet.remove(urlHostHash(group->manifestURL())); -} - -void ApplicationCacheStorage::setCacheDirectory(const String& cacheDirectory) -{ - ASSERT(m_cacheDirectory.isNull()); - ASSERT(!cacheDirectory.isNull()); - - m_cacheDirectory = cacheDirectory; -} - -bool ApplicationCacheStorage::executeSQLCommand(const String& sql) -{ - ASSERT(m_database.isOpen()); - - bool result = m_database.executeCommand(sql); - if (!result) - LOG_ERROR("Application Cache Storage: failed to execute statement \"%s\" error \"%s\"", - sql.utf8().data(), m_database.lastErrorMsg()); - - return result; -} - -static const int SchemaVersion = 2; - -void ApplicationCacheStorage::verifySchemaVersion() -{ - if (m_database.tableExists("SchemaVersion")) { - int version = SQLiteStatement(m_database, "SELECT version from SchemaVersion").getColumnInt(0); - - if (version == SchemaVersion) - return; - } - - m_database.clearAllTables(); - - SQLiteTransaction createSchemaVersionTable(m_database); - createSchemaVersionTable.begin(); - - executeSQLCommand("CREATE TABLE SchemaVersion (version INTEGER NOT NULL)"); - SQLiteStatement statement(m_database, "INSERT INTO SchemaVersion (version) VALUES (?)"); - if (statement.prepare() != SQLResultOk) - return; - - statement.bindInt64(1, SchemaVersion); - executeStatement(statement); - createSchemaVersionTable.commit(); -} - -void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist) -{ - if (m_database.isOpen()) - return; - - // The cache directory should never be null, but if it for some weird reason is we bail out. - if (m_cacheDirectory.isNull()) - return; - - String applicationCachePath = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db"); - if (!createIfDoesNotExist && !fileExists(applicationCachePath)) - return; - - makeAllDirectories(m_cacheDirectory); - m_database.open(applicationCachePath); - - if (!m_database.isOpen()) - return; - - verifySchemaVersion(); - - // Create tables - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheGroups (id INTEGER PRIMARY KEY AUTOINCREMENT, " - "manifestHostHash INTEGER NOT NULL ON CONFLICT FAIL, manifestURL TEXT UNIQUE ON CONFLICT FAIL, newestCache INTEGER)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheWhitelistURLs (url TEXT NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS FallbackURLs (namespace TEXT NOT NULL ON CONFLICT FAIL, fallbackURL TEXT NOT NULL ON CONFLICT FAIL, " - "cache INTEGER NOT NULL ON CONFLICT FAIL)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheEntries (cache INTEGER NOT NULL ON CONFLICT FAIL, type INTEGER, resource INTEGER NOT NULL)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResources (id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL ON CONFLICT FAIL, " - "statusCode INTEGER NOT NULL, responseURL TEXT NOT NULL, mimeType TEXT, textEncodingName TEXT, headers TEXT, data INTEGER NOT NULL ON CONFLICT FAIL)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheResourceData (id INTEGER PRIMARY KEY AUTOINCREMENT, data BLOB)"); - - // When a cache is deleted, all its entries and its whitelist should be deleted. - executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheDeleted AFTER DELETE ON Caches" - " FOR EACH ROW BEGIN" - " DELETE FROM CacheEntries WHERE cache = OLD.id;" - " DELETE FROM CacheWhitelistURLs WHERE cache = OLD.id;" - " DELETE FROM FallbackURLs WHERE cache = OLD.id;" - " END"); - - // When a cache resource is deleted, its data blob should also be deleted. - executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheResourceDeleted AFTER DELETE ON CacheResources" - " FOR EACH ROW BEGIN" - " DELETE FROM CacheResourceData WHERE id = OLD.data;" - " END"); -} - -bool ApplicationCacheStorage::executeStatement(SQLiteStatement& statement) -{ - bool result = statement.executeCommand(); - if (!result) - LOG_ERROR("Application Cache Storage: failed to execute statement \"%s\" error \"%s\"", - statement.query().utf8().data(), m_database.lastErrorMsg()); - - return result; -} - -bool ApplicationCacheStorage::store(ApplicationCacheGroup* group) -{ - ASSERT(group->storageID() == 0); - - SQLiteStatement statement(m_database, "INSERT INTO CacheGroups (manifestHostHash, manifestURL) VALUES (?, ?)"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindInt64(1, urlHostHash(group->manifestURL())); - statement.bindText(2, group->manifestURL()); - - if (!executeStatement(statement)) - return false; - - group->setStorageID((unsigned)m_database.lastInsertRowID()); - return true; -} - -bool ApplicationCacheStorage::store(ApplicationCache* cache) -{ - ASSERT(cache->storageID() == 0); - ASSERT(cache->group()->storageID() != 0); - - SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup) VALUES (?)"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindInt64(1, cache->group()->storageID()); - - if (!executeStatement(statement)) - return false; - - unsigned cacheStorageID = (unsigned)m_database.lastInsertRowID(); - - // Store all resources - { - ApplicationCache::ResourceMap::const_iterator end = cache->end(); - for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { - if (!store(it->second.get(), cacheStorageID)) - return false; - } - } - - // Store the online whitelist - const HashSet<String>& onlineWhitelist = cache->onlineWhitelist(); - { - HashSet<String>::const_iterator end = onlineWhitelist.end(); - for (HashSet<String>::const_iterator it = onlineWhitelist.begin(); it != end; ++it) { - SQLiteStatement statement(m_database, "INSERT INTO CacheWhitelistURLs (url, cache) VALUES (?, ?)"); - statement.prepare(); - - statement.bindText(1, *it); - statement.bindInt64(2, cacheStorageID); - - if (!executeStatement(statement)) - return false; - } - } - - cache->setStorageID(cacheStorageID); - return true; -} - -bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned cacheStorageID) -{ - ASSERT(cacheStorageID); - ASSERT(!resource->storageID()); - - openDatabase(true); - - // First, insert the data - SQLiteStatement dataStatement(m_database, "INSERT INTO CacheResourceData (data) VALUES (?)"); - if (dataStatement.prepare() != SQLResultOk) - return false; - - if (resource->data()->size()) - dataStatement.bindBlob(1, resource->data()->data(), resource->data()->size()); - - if (!dataStatement.executeCommand()) - return false; - - unsigned dataId = (unsigned)m_database.lastInsertRowID(); - - // Then, insert the resource - - // Serialize the headers - Vector<UChar> stringBuilder; - - HTTPHeaderMap::const_iterator end = resource->response().httpHeaderFields().end(); - for (HTTPHeaderMap::const_iterator it = resource->response().httpHeaderFields().begin(); it!= end; ++it) { - stringBuilder.append(it->first.characters(), it->first.length()); - stringBuilder.append((UChar)':'); - stringBuilder.append(it->second.characters(), it->second.length()); - stringBuilder.append((UChar)'\n'); - } - - String headers = String::adopt(stringBuilder); - - SQLiteStatement resourceStatement(m_database, "INSERT INTO CacheResources (url, statusCode, responseURL, headers, data, mimeType, textEncodingName) VALUES (?, ?, ?, ?, ?, ?, ?)"); - if (resourceStatement.prepare() != SQLResultOk) - return false; - - resourceStatement.bindText(1, resource->url()); - resourceStatement.bindInt64(2, resource->response().httpStatusCode()); - resourceStatement.bindText(3, resource->response().url()); - resourceStatement.bindText(4, headers); - resourceStatement.bindInt64(5, dataId); - resourceStatement.bindText(6, resource->response().mimeType()); - resourceStatement.bindText(7, resource->response().textEncodingName()); - - if (!executeStatement(resourceStatement)) - return false; - - unsigned resourceId = (unsigned)m_database.lastInsertRowID(); - - // Finally, insert the cache entry - SQLiteStatement entryStatement(m_database, "INSERT INTO CacheEntries (cache, type, resource) VALUES (?, ?, ?)"); - if (entryStatement.prepare() != SQLResultOk) - return false; - - entryStatement.bindInt64(1, cacheStorageID); - entryStatement.bindInt64(2, resource->type()); - entryStatement.bindInt64(3, resourceId); - - if (!executeStatement(entryStatement)) - return false; - - resource->setStorageID(resourceId); - return true; -} - -void ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache) -{ - ASSERT(cache->storageID()); - - openDatabase(true); - - SQLiteTransaction storeResourceTransaction(m_database); - storeResourceTransaction.begin(); - - if (!store(resource, cache->storageID())) - return; - - storeResourceTransaction.commit(); -} - -bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup* group) -{ - openDatabase(true); - - SQLiteTransaction storeCacheTransaction(m_database); - - storeCacheTransaction.begin(); - - if (!group->storageID()) { - // Store the group - if (!store(group)) - return false; - } - - ASSERT(group->newestCache()); - ASSERT(!group->newestCache()->storageID()); - - // Store the newest cache - if (!store(group->newestCache())) - return false; - - // Update the newest cache in the group. - - SQLiteStatement statement(m_database, "UPDATE CacheGroups SET newestCache=? WHERE id=?"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindInt64(1, group->newestCache()->storageID()); - statement.bindInt64(2, group->storageID()); - - if (!executeStatement(statement)) - return false; - - storeCacheTransaction.commit(); - return true; -} - -static inline void parseHeader(const UChar* header, size_t headerLength, ResourceResponse& response) -{ - int pos = find(header, headerLength, ':'); - ASSERT(pos != -1); - - String headerName = String(header, pos); - String headerValue = String(header + pos + 1, headerLength - pos - 1); - - response.setHTTPHeaderField(headerName, headerValue); -} - -static inline void parseHeaders(const String& headers, ResourceResponse& response) -{ - int startPos = 0; - int endPos; - while ((endPos = headers.find('\n', startPos)) != -1) { - ASSERT(startPos != endPos); - - parseHeader(headers.characters() + startPos, endPos - startPos, response); - - startPos = endPos + 1; - } - - if (startPos != static_cast<int>(headers.length())) - parseHeader(headers.characters(), headers.length(), response); -} - -PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID) -{ - SQLiteStatement cacheStatement(m_database, - "SELECT url, type, mimeType, textEncodingName, headers, CacheResourceData.data FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id " - "INNER JOIN CacheResourceData ON CacheResourceData.id=CacheResources.data WHERE CacheEntries.cache=?"); - if (cacheStatement.prepare() != SQLResultOk) { - LOG_ERROR("Could not prepare cache statement, error \"%s\"", m_database.lastErrorMsg()); - return 0; - } - - cacheStatement.bindInt64(1, storageID); - - RefPtr<ApplicationCache> cache = ApplicationCache::create(); - - int result; - while ((result = cacheStatement.step()) == SQLResultRow) { - KURL url(cacheStatement.getColumnText(0)); - - unsigned type = (unsigned)cacheStatement.getColumnInt64(1); - - Vector<char> blob; - cacheStatement.getColumnBlobAsVector(5, blob); - - RefPtr<SharedBuffer> data = SharedBuffer::adoptVector(blob); - - String mimeType = cacheStatement.getColumnText(2); - String textEncodingName = cacheStatement.getColumnText(3); - - ResourceResponse response(url, mimeType, data->size(), textEncodingName, ""); - - String headers = cacheStatement.getColumnText(4); - parseHeaders(headers, response); - - RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, response, type, data.release()); - - if (type & ApplicationCacheResource::Manifest) - cache->setManifestResource(resource.release()); - else - cache->addResource(resource.release()); - } - - if (result != SQLResultDone) - LOG_ERROR("Could not load cache resources, error \"%s\"", m_database.lastErrorMsg()); - - // Load the online whitelist - SQLiteStatement whitelistStatement(m_database, "SELECT url FROM CacheWhitelistURLs WHERE cache=?"); - if (whitelistStatement.prepare() != SQLResultOk) - return 0; - whitelistStatement.bindInt64(1, storageID); - - HashSet<String> whitelist; - while ((result = whitelistStatement.step()) == SQLResultRow) - whitelist.add(whitelistStatement.getColumnText(0)); - - if (result != SQLResultDone) - LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg()); - - cache->setOnlineWhitelist(whitelist); - - cache->setStorageID(storageID); - - return cache.release(); -} - -void ApplicationCacheStorage::remove(ApplicationCache* cache) -{ - if (!cache->storageID()) - return; - - openDatabase(false); - if (!m_database.isOpen()) - return; - - SQLiteStatement statement(m_database, "DELETE FROM Caches WHERE id=?"); - if (statement.prepare() != SQLResultOk) - return; - - statement.bindInt64(1, cache->storageID()); - executeStatement(statement); -} - -void ApplicationCacheStorage::empty() -{ - openDatabase(false); - - if (!m_database.isOpen()) - return; - - // Clear cache groups, caches and cache resources. - executeSQLCommand("DELETE FROM CacheGroups"); - executeSQLCommand("DELETE FROM Caches"); - executeSQLCommand("DELETE FROM CacheResources"); - - // Clear the storage IDs for the caches in memory. - // The caches will still work, but cached resources will not be saved to disk - // until a cache update process has been initiated. - CacheGroupMap::const_iterator end = m_cachesInMemory.end(); - for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) - it->second->clearStorageID(); -} - -bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCache* cache) -{ - // Create a new cache. - RefPtr<ApplicationCache> cacheCopy = ApplicationCache::create(); - - // Set the online whitelist - cacheCopy->setOnlineWhitelist(cache->onlineWhitelist()); - - // Traverse the cache and add copies of all resources. - ApplicationCache::ResourceMap::const_iterator end = cache->end(); - for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { - ApplicationCacheResource* resource = it->second.get(); - - RefPtr<ApplicationCacheResource> resourceCopy = ApplicationCacheResource::create(resource->url(), resource->response(), resource->type(), resource->data()); - - cacheCopy->addResource(resourceCopy.release()); - } - - // Now create a new cache group. - OwnPtr<ApplicationCacheGroup> groupCopy(new ApplicationCacheGroup(cache->group()->manifestURL(), true)); - - groupCopy->setNewestCache(cacheCopy); - - ApplicationCacheStorage copyStorage; - copyStorage.setCacheDirectory(cacheDirectory); - - // Empty the cache in case something was there before. - copyStorage.empty(); - - return copyStorage.storeNewestCache(groupCopy.get()); -} - -ApplicationCacheStorage& cacheStorage() -{ - static ApplicationCacheStorage storage; - - return storage; -} - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ApplicationCacheStorage.h b/WebCore/loader/appcache/ApplicationCacheStorage.h deleted file mode 100644 index 6bd9ba1..0000000 --- a/WebCore/loader/appcache/ApplicationCacheStorage.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ApplicationCacheStorage_h -#define ApplicationCacheStorage_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "PlatformString.h" -#include "SQLiteDatabase.h" -#include "StringHash.h" - -#include <wtf/HashCountedSet.h> - -namespace WebCore { - -class ApplicationCache; -class ApplicationCacheGroup; -class ApplicationCacheResource; -class KURL; - -class ApplicationCacheStorage { -public: - void setCacheDirectory(const String&); - - ApplicationCacheGroup* cacheGroupForURL(const KURL&); - - ApplicationCacheGroup* findOrCreateCacheGroup(const KURL& manifestURL); - void cacheGroupDestroyed(ApplicationCacheGroup*); - - bool storeNewestCache(ApplicationCacheGroup*); - void store(ApplicationCacheResource*, ApplicationCache*); - - void remove(ApplicationCache*); - - void empty(); - - static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCache*); -private: - PassRefPtr<ApplicationCache> loadCache(unsigned storageID); - ApplicationCacheGroup* loadCacheGroup(const KURL& manifestURL); - - bool store(ApplicationCacheGroup*); - bool store(ApplicationCache*); - bool store(ApplicationCacheResource*, unsigned cacheStorageID); - - void loadManifestHostHashes(); - - void verifySchemaVersion(); - - void openDatabase(bool createIfDoesNotExist); - - bool executeStatement(SQLiteStatement&); - bool executeSQLCommand(const String&); - - String m_cacheDirectory; - - SQLiteDatabase m_database; - - // In order to quickly determinate if a given resource exists in an application cache, - // we keep a hash set of the hosts of the manifest URLs of all cache groups. - HashCountedSet<unsigned, AlreadyHashed> m_cacheHostSet; - - typedef HashMap<String, ApplicationCacheGroup*> CacheGroupMap; - CacheGroupMap m_cachesInMemory; -}; - -ApplicationCacheStorage& cacheStorage(); - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ApplicationCacheStorage_h diff --git a/WebCore/loader/appcache/DOMApplicationCache.cpp b/WebCore/loader/appcache/DOMApplicationCache.cpp deleted file mode 100644 index f872a50..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DOMApplicationCache.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCache.h" -#include "ApplicationCacheGroup.h" -#include "DocumentLoader.h" -#include "Event.h" -#include "EventException.h" -#include "EventListener.h" -#include "EventNames.h" -#include "Frame.h" -#include "FrameLoader.h" - -namespace WebCore { - -DOMApplicationCache::DOMApplicationCache(Frame* frame) - : m_frame(frame) -{ -} - -void DOMApplicationCache::disconnectFrame() -{ - m_frame = 0; -} - -ApplicationCache* DOMApplicationCache::associatedCache() const -{ - if (!m_frame) - return 0; - - return m_frame->loader()->documentLoader()->topLevelApplicationCache(); -} - -unsigned short DOMApplicationCache::status() const -{ - ApplicationCache* cache = associatedCache(); - if (!cache) - return UNCACHED; - - switch (cache->group()->status()) { - case ApplicationCacheGroup::Checking: - return CHECKING; - case ApplicationCacheGroup::Downloading: - return DOWNLOADING; - case ApplicationCacheGroup::Idle: { - if (cache != cache->group()->newestCache()) - return UPDATEREADY; - - return IDLE; - } - default: - ASSERT_NOT_REACHED(); - } - - return 0; -} - -void DOMApplicationCache::update(ExceptionCode& ec) -{ - ApplicationCache* cache = associatedCache(); - if (!cache) { - ec = INVALID_STATE_ERR; - return; - } - - cache->group()->update(m_frame); -} - -bool DOMApplicationCache::swapCache() -{ - if (!m_frame) - return false; - - ApplicationCache* cache = m_frame->loader()->documentLoader()->applicationCache(); - if (!cache) - return false; - - // Check if we already have the newest cache - ApplicationCache* newestCache = cache->group()->newestCache(); - if (cache == newestCache) - return false; - - ASSERT(cache->group() == newestCache->group()); - m_frame->loader()->documentLoader()->setApplicationCache(newestCache); - - return true; -} - -void DOMApplicationCache::swapCache(ExceptionCode& ec) -{ - if (!swapCache()) - ec = INVALID_STATE_ERR; -} - -unsigned DOMApplicationCache::length() const -{ - ApplicationCache* cache = associatedCache(); - if (!cache) - return 0; - - return cache->numDynamicEntries(); -} - -String DOMApplicationCache::item(unsigned item, ExceptionCode& ec) -{ - ApplicationCache* cache = associatedCache(); - if (!cache) { - ec = INVALID_STATE_ERR; - return String(); - } - - if (item >= length()) { - ec = INDEX_SIZE_ERR; - return String(); - } - - return cache->dynamicEntry(item); -} - -void DOMApplicationCache::add(const KURL& url, ExceptionCode& ec) -{ - ApplicationCache* cache = associatedCache(); - if (!cache) { - ec = INVALID_STATE_ERR; - return; - } - - if (!url.isValid()) { - ec = SYNTAX_ERR; - return; - } - - if (!cache->addDynamicEntry(url)) { - // This should use the (currently not specified) security exceptions in HTML5 4.3.4 - ec = SECURITY_ERR; - } -} - -void DOMApplicationCache::remove(const KURL& url, ExceptionCode& ec) -{ - ApplicationCache* cache = associatedCache(); - if (!cache) { - ec = INVALID_STATE_ERR; - return; - } - - cache->removeDynamicEntry(url); -} - -ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const -{ - return m_frame->document(); -} - -void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) { - ListenerVector listeners; - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } else { - ListenerVector& listeners = iter->second; - for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) - return; - } - - listeners.append(eventListener); - m_eventListeners.add(eventType, listeners); - } -} - -void DOMApplicationCache::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool useCapture) -{ - EventListenersMap::iterator iter = m_eventListeners.find(eventType); - if (iter == m_eventListeners.end()) - return; - - ListenerVector& listeners = iter->second; - for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) { - if (*listenerIter == eventListener) { - listeners.remove(listenerIter - listeners.begin()); - return; - } - } -} - -bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) -{ - if (event->type().isEmpty()) { - ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; - return true; - } - - ListenerVector listenersCopy = m_eventListeners.get(event->type()); - for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) { - event->setTarget(this); - event->setCurrentTarget(this); - listenerIter->get()->handleEvent(event.get(), false); - } - - return !event->defaultPrevented(); -} - -void DOMApplicationCache::callListener(const AtomicString& eventType, EventListener* listener) -{ - ASSERT(m_frame); - - RefPtr<Event> event = Event::create(eventType, false, false); - if (listener) { - event->setTarget(this); - event->setCurrentTarget(this); - listener->handleEvent(event.get(), false); - } - - ExceptionCode ec = 0; - dispatchEvent(event.release(), ec); - ASSERT(!ec); -} - -void DOMApplicationCache::callCheckingListener() -{ - callListener(eventNames().checkingEvent, m_onCheckingListener.get()); -} - -void DOMApplicationCache::callErrorListener() -{ - callListener(eventNames().errorEvent, m_onErrorListener.get()); -} - -void DOMApplicationCache::callNoUpdateListener() -{ - callListener(eventNames().noupdateEvent, m_onNoUpdateListener.get()); -} - -void DOMApplicationCache::callDownloadingListener() -{ - callListener(eventNames().downloadingEvent, m_onDownloadingListener.get()); -} - -void DOMApplicationCache::callProgressListener() -{ - callListener(eventNames().progressEvent, m_onProgressListener.get()); -} - -void DOMApplicationCache::callUpdateReadyListener() -{ - callListener(eventNames().updatereadyEvent, m_onUpdateReadyListener.get()); -} - -void DOMApplicationCache::callCachedListener() -{ - callListener(eventNames().cachedEvent, m_onCachedListener.get()); -} - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/DOMApplicationCache.h b/WebCore/loader/appcache/DOMApplicationCache.h deleted file mode 100644 index 30c0b7e..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DOMApplicationCache_h -#define DOMApplicationCache_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "AtomicStringHash.h" -#include "EventTarget.h" -#include "EventListener.h" -#include <wtf/HashMap.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class ApplicationCache; -class AtomicStringImpl; -class Frame; -class KURL; -class String; - -class DOMApplicationCache : public RefCounted<DOMApplicationCache>, public EventTarget { -public: - static PassRefPtr<DOMApplicationCache> create(Frame* frame) { return adoptRef(new DOMApplicationCache(frame)); } - void disconnectFrame(); - - enum Status { - UNCACHED = 0, - IDLE = 1, - CHECKING = 2, - DOWNLOADING = 3, - UPDATEREADY = 4, - }; - - unsigned short status() const; - - void update(ExceptionCode&); - void swapCache(ExceptionCode&); - - unsigned length() const; - String item(unsigned item, ExceptionCode&); - void add(const KURL&, ExceptionCode&); - void remove(const KURL&, ExceptionCode&); - - virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); - - typedef Vector<RefPtr<EventListener> > ListenerVector; - typedef HashMap<AtomicString, ListenerVector> EventListenersMap; - EventListenersMap& eventListeners() { return m_eventListeners; } - - using RefCounted<DOMApplicationCache>::ref; - using RefCounted<DOMApplicationCache>::deref; - - void setOnchecking(PassRefPtr<EventListener> eventListener) { m_onCheckingListener = eventListener; } - EventListener* onchecking() const { return m_onCheckingListener.get(); } - - void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; } - EventListener* onerror() const { return m_onErrorListener.get(); } - - void setOnnoupdate(PassRefPtr<EventListener> eventListener) { m_onNoUpdateListener = eventListener; } - EventListener* onnoupdate() const { return m_onNoUpdateListener.get(); } - - void setOndownloading(PassRefPtr<EventListener> eventListener) { m_onDownloadingListener = eventListener; } - EventListener* ondownloading() const { return m_onDownloadingListener.get(); } - - void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; } - EventListener* onprogress() const { return m_onProgressListener.get(); } - - void setOnupdateready(PassRefPtr<EventListener> eventListener) { m_onUpdateReadyListener = eventListener; } - EventListener* onupdateready() const { return m_onUpdateReadyListener.get(); } - - void setOncached(PassRefPtr<EventListener> eventListener) { m_onCachedListener = eventListener; } - EventListener* oncached() const { return m_onCachedListener.get(); } - - virtual ScriptExecutionContext* scriptExecutionContext() const; - DOMApplicationCache* toDOMApplicationCache() { return this; } - - void callCheckingListener(); - void callErrorListener(); - void callNoUpdateListener(); - void callDownloadingListener(); - void callProgressListener(); - void callUpdateReadyListener(); - void callCachedListener(); - -private: - DOMApplicationCache(Frame*); - void callListener(const AtomicString& eventType, EventListener*); - - virtual void refEventTarget() { ref(); } - virtual void derefEventTarget() { deref(); } - - ApplicationCache* associatedCache() const; - bool swapCache(); - - RefPtr<EventListener> m_onCheckingListener; - RefPtr<EventListener> m_onErrorListener; - RefPtr<EventListener> m_onNoUpdateListener; - RefPtr<EventListener> m_onDownloadingListener; - RefPtr<EventListener> m_onProgressListener; - RefPtr<EventListener> m_onUpdateReadyListener; - RefPtr<EventListener> m_onCachedListener; - - EventListenersMap m_eventListeners; - - Frame* m_frame; -}; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // DOMApplicationCache_h diff --git a/WebCore/loader/appcache/DOMApplicationCache.idl b/WebCore/loader/appcache/DOMApplicationCache.idl deleted file mode 100644 index 94326f3..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.idl +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -module offline { - - interface [ - Conditional=OFFLINE_WEB_APPLICATIONS, - CustomMarkFunction - ] DOMApplicationCache { - // update status - const unsigned short UNCACHED = 0; - const unsigned short IDLE = 1; - const unsigned short CHECKING = 2; - const unsigned short DOWNLOADING = 3; - const unsigned short UPDATEREADY = 4; - readonly attribute unsigned short status; - - void update() - raises(DOMException); - void swapCache() - raises(DOMException); - - // dynamic entries - readonly attribute unsigned long length; - DOMString item(in [IsIndex] unsigned long index) - raises(DOMException); - [Custom] void add(in DOMString uri) - raises(DOMException); - [Custom] void remove(in DOMString uri) - raises(DOMException); - - // events - attribute EventListener onchecking; - attribute EventListener onerror; - attribute EventListener onnoupdate; - attribute EventListener ondownloading; - attribute EventListener onprogress; - attribute EventListener onupdateready; - attribute EventListener oncached; - - // EventTarget interface - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - boolean dispatchEvent(in Event evt) - raises(EventException); - }; - -} diff --git a/WebCore/loader/appcache/ManifestParser.cpp b/WebCore/loader/appcache/ManifestParser.cpp deleted file mode 100644 index 778d22d..0000000 --- a/WebCore/loader/appcache/ManifestParser.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ManifestParser.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "CharacterNames.h" -#include "KURL.h" -#include "TextEncoding.h" - -namespace WebCore { - -enum Mode { Explicit, Fallback, OnlineWhitelist }; - -bool parseManifest(const KURL& manifestURL, const char* data, int length, Manifest& manifest) -{ - ASSERT(manifest.explicitURLs.isEmpty()); - ASSERT(manifest.onlineWhitelistedURLs.isEmpty()); - ASSERT(manifest.fallbackURLs.isEmpty()); - - Mode mode = Explicit; - String s = UTF8Encoding().decode(data, length); - - if (s.isEmpty()) - return false; - - // Replace nulls with U+FFFD REPLACEMENT CHARACTER - s.replace(0, replacementCharacter); - - // Look for the magic signature - if (!s.startsWith("CACHE MANIFEST")) { - // The magic signature was not found. - return false; - } - - const UChar* end = s.characters() + s.length(); - const UChar* p = s.characters() + 14; // "CACHE MANIFEST" is 14 characters. - - while (p < end) { - // Skip whitespace - if (*p == ' ' || *p == '\t') { - p++; - } else - break; - } - - if (p < end && *p != '\n' && *p != '\r') { - // The magic signature was invalid - return false; - } - - while (1) { - // Skip whitespace - while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t')) - p++; - - if (p == end) - break; - - const UChar* lineStart = p; - - // Find the end of the line - while (p < end && *p != '\r' && *p != '\n') - p++; - - // Check if we have a comment - if (*lineStart == '#') - continue; - - // Get rid of trailing whitespace - const UChar* tmp = p - 1; - while (tmp > lineStart && (*tmp == ' ' || *tmp == '\t')) - tmp--; - - String line(lineStart, tmp - lineStart + 1); - - if (line == "CACHE:") - mode = Explicit; - else if (line == "FALLBACK:") - mode = Fallback; - else if (line == "NETWORK:") - mode = OnlineWhitelist; - else if (mode == Explicit || mode == OnlineWhitelist) { - KURL url(manifestURL, line); - - if (!url.isValid()) - continue; - - if (url.hasRef()) - url.setRef(String()); - - if (!equalIgnoringCase(url.protocol(), manifestURL.protocol())) - continue; - - if (mode == Explicit) - manifest.explicitURLs.add(url.string()); - else - manifest.onlineWhitelistedURLs.add(url.string()); - - } else if (mode == Fallback) { - const UChar *p = line.characters(); - const UChar *lineEnd = p + line.length(); - - // Look for whitespace separating the two URLs - while (p < lineEnd && *p != '\t' && *p != ' ') - p++; - - if (p == lineEnd) { - // There was no whitespace separating the URLs. - continue; - } - - KURL namespaceURL(manifestURL, String(line.characters(), p - line.characters())); - if (!namespaceURL.isValid()) - continue; - - // Check that the namespace URL has the same scheme/host/port as the manifest URL. - if (!protocolHostAndPortAreEqual(manifestURL, namespaceURL)) - continue; - - while (p < lineEnd && (*p == '\t' || *p == ' ')) - p++; - - KURL fallbackURL(String(p, line.length() - (p - line.characters()))); - - if (!fallbackURL.isValid()) - continue; - - if (!equalIgnoringCase(fallbackURL.protocol(), manifestURL.protocol())) - continue; - - manifest.fallbackURLs.add(namespaceURL, fallbackURL); - } else - ASSERT_NOT_REACHED(); - } - - return true; -} - -} - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ManifestParser.h b/WebCore/loader/appcache/ManifestParser.h deleted file mode 100644 index f4fe31a..0000000 --- a/WebCore/loader/appcache/ManifestParser.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ManifestParser_h -#define ManifestParser_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include "StringHash.h" -#include "PlatformString.h" - -namespace WebCore { - -class KURL; - -struct Manifest { - HashSet<String> onlineWhitelistedURLs; - HashSet<String> explicitURLs; - HashMap<String, String> fallbackURLs; -}; - -bool parseManifest(const KURL& manifestURL, const char* data, int length, Manifest&); - -} - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ManifestParser_h diff --git a/WebCore/loader/archive/Archive.h b/WebCore/loader/archive/Archive.h deleted file mode 100644 index af3d8b1..0000000 --- a/WebCore/loader/archive/Archive.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef Archive_h -#define Archive_h - -#include "ArchiveResource.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class Archive : public RefCounted<Archive> { -public: - ArchiveResource* mainResource() { return m_mainResource.get(); } - const Vector<RefPtr<ArchiveResource> >& subresources() const { return m_subresources; } - const Vector<RefPtr<Archive> >& subframeArchives() const { return m_subframeArchives; } - -protected: - // These methods are meant for subclasses for different archive types to add resources in to the archive, - // and should not be exposed as archives should be immutable to clients - void setMainResource(PassRefPtr<ArchiveResource> mainResource) { m_mainResource = mainResource; } - void addSubresource(PassRefPtr<ArchiveResource> subResource) { m_subresources.append(subResource); } - void addSubframeArchive(PassRefPtr<Archive> subframeArchive) { m_subframeArchives.append(subframeArchive); } - -private: - RefPtr<ArchiveResource> m_mainResource; - Vector<RefPtr<ArchiveResource> > m_subresources; - Vector<RefPtr<Archive> > m_subframeArchives; -}; - -} - -#endif // Archive diff --git a/WebCore/loader/archive/ArchiveFactory.cpp b/WebCore/loader/archive/ArchiveFactory.cpp deleted file mode 100644 index c42b5df..0000000 --- a/WebCore/loader/archive/ArchiveFactory.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ArchiveFactory.h" - -#if PLATFORM(CF) -#include "LegacyWebArchive.h" -#endif -#include "MIMETypeRegistry.h" -#include "PlatformString.h" - -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> - -namespace WebCore { - -typedef PassRefPtr<Archive> RawDataCreationFunction(SharedBuffer*); - -// The create functions in the archive classes return PassRefPtr to concrete subclasses -// of Archive. This adaptor makes the functions have a uniform return type. -template <typename ArchiveClass> static PassRefPtr<Archive> archiveFactoryCreate(SharedBuffer* buffer) -{ - return ArchiveClass::create(buffer); -} - -static HashMap<String, RawDataCreationFunction*, CaseFoldingHash>& archiveMIMETypes() -{ - static HashMap<String, RawDataCreationFunction*, CaseFoldingHash> mimeTypes; - static bool initialized = false; - - if (initialized) - return mimeTypes; - -#if PLATFORM(CF) - mimeTypes.set("application/x-webarchive", archiveFactoryCreate<LegacyWebArchive>); -#endif - - initialized = true; - return mimeTypes; -} - -bool ArchiveFactory::isArchiveMimeType(const String& mimeType) -{ - return archiveMIMETypes().contains(mimeType); -} - -PassRefPtr<Archive> ArchiveFactory::create(SharedBuffer* data, const String& mimeType) -{ - RawDataCreationFunction* function = archiveMIMETypes().get(mimeType); - return function ? function(data) : 0; -} - -void ArchiveFactory::registerKnownArchiveMIMETypes() -{ - HashSet<String>& mimeTypes = MIMETypeRegistry::getSupportedNonImageMIMETypes(); - HashMap<String, RawDataCreationFunction*, CaseFoldingHash>::iterator i = archiveMIMETypes().begin(); - HashMap<String, RawDataCreationFunction*, CaseFoldingHash>::iterator end = archiveMIMETypes().end(); - - for (; i != end; ++i) - mimeTypes.add(i->first); -} - -} diff --git a/WebCore/loader/archive/ArchiveFactory.h b/WebCore/loader/archive/ArchiveFactory.h deleted file mode 100644 index bf1d5c6..0000000 --- a/WebCore/loader/archive/ArchiveFactory.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ArchiveFactory_h -#define ArchiveFactory_h - -#include "Archive.h" - -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -class SharedBuffer; -class String; - -class ArchiveFactory { -public: - static bool isArchiveMimeType(const String&); - static PassRefPtr<Archive> create(SharedBuffer* data, const String& mimeType); - static void registerKnownArchiveMIMETypes(); -}; - -} - -#endif // ArchiveFactory_h diff --git a/WebCore/loader/archive/ArchiveResource.cpp b/WebCore/loader/archive/ArchiveResource.cpp deleted file mode 100644 index 691f66a..0000000 --- a/WebCore/loader/archive/ArchiveResource.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ArchiveResource.h" - -#include "SharedBuffer.h" - -namespace WebCore { - -PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const ResourceResponse& response) -{ - return data ? adoptRef(new ArchiveResource(data, url, response)) : 0; -} - -PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName) -{ - return data ? adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName)) : 0; -} - -PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& resourceResponse) -{ - return data ? adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName, resourceResponse)) : 0; -} - -ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const ResourceResponse& response) - : SubstituteResource(url, response, data) - , m_mimeType(response.mimeType()) - , m_textEncoding(response.textEncodingName()) - , m_shouldIgnoreWhenUnarchiving(false) -{ -} - -ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName) - : SubstituteResource(url, ResourceResponse(url, mimeType, data ? data->size() : 0, textEncoding, String()), data) - , m_mimeType(mimeType) - , m_textEncoding(textEncoding) - , m_frameName(frameName) - , m_shouldIgnoreWhenUnarchiving(false) -{ -} - -ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& response) - : SubstituteResource(url, response.isNull() ? ResourceResponse(url, mimeType, data ? data->size() : 0, textEncoding, String()) : response, data) - , m_mimeType(mimeType) - , m_textEncoding(textEncoding) - , m_frameName(frameName) - , m_shouldIgnoreWhenUnarchiving(false) -{ -} - -} diff --git a/WebCore/loader/archive/ArchiveResource.h b/WebCore/loader/archive/ArchiveResource.h deleted file mode 100644 index d975e04..0000000 --- a/WebCore/loader/archive/ArchiveResource.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ArchiveResource_h -#define ArchiveResource_h - -#include "SubstituteResource.h" - -#include "PlatformString.h" - -namespace WebCore { - -class ArchiveResource : public SubstituteResource { -public: - static PassRefPtr<ArchiveResource> create(PassRefPtr<SharedBuffer>, const KURL&, const ResourceResponse&); - static PassRefPtr<ArchiveResource> create(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName); - static PassRefPtr<ArchiveResource> create(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse&); - - const String& mimeType() const { return m_mimeType; } - const String& textEncoding() const { return m_textEncoding; } - const String& frameName() const { return m_frameName; } - - void ignoreWhenUnarchiving() { m_shouldIgnoreWhenUnarchiving = true; } - bool shouldIgnoreWhenUnarchiving() const { return m_shouldIgnoreWhenUnarchiving; } - -private: - ArchiveResource(PassRefPtr<SharedBuffer>, const KURL&, const ResourceResponse&); - ArchiveResource(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName); - ArchiveResource(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse&); - - String m_mimeType; - String m_textEncoding; - String m_frameName; - - bool m_shouldIgnoreWhenUnarchiving; -}; - -} - -#endif // ArchiveResource_h diff --git a/WebCore/loader/archive/ArchiveResourceCollection.cpp b/WebCore/loader/archive/ArchiveResourceCollection.cpp deleted file mode 100644 index 6eb1237..0000000 --- a/WebCore/loader/archive/ArchiveResourceCollection.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ArchiveResourceCollection.h" - -namespace WebCore { - -ArchiveResourceCollection::ArchiveResourceCollection() -{ -} - -void ArchiveResourceCollection::addAllResources(Archive* archive) -{ - ASSERT(archive); - if (!archive) - return; - - const Vector<RefPtr<ArchiveResource> >& subresources = archive->subresources(); - Vector<RefPtr<ArchiveResource> >::const_iterator iRes = subresources.begin(); - Vector<RefPtr<ArchiveResource> >::const_iterator endRes = subresources.end(); - - for (; iRes != endRes; ++iRes) - m_subresources.set((*iRes)->url(), iRes->get()); - - const Vector<RefPtr<Archive> >& subframes = archive->subframeArchives(); - Vector<RefPtr<Archive> >::const_iterator iFrame = subframes.begin(); - Vector<RefPtr<Archive> >::const_iterator endFrame = subframes.end(); - - for (; iFrame != endFrame; ++iFrame) { - ASSERT((*iFrame)->mainResource()); - const String& frameName = (*iFrame)->mainResource()->frameName(); - if (!frameName.isNull()) - m_subframes.set(frameName, iFrame->get()); - } -} - -// FIXME: Adding a resource directly to a DocumentLoader/ArchiveResourceCollection seems like bad design, but is API some apps rely on. -// Can we change the design in a manner that will let us deprecate that API without reducing functionality of those apps? -void ArchiveResourceCollection::addResource(PassRefPtr<ArchiveResource> resource) -{ - ASSERT(resource); - if (!resource) - return; - - const KURL& url = resource->url(); // get before passing PassRefPtr (which sets it to 0) - m_subresources.set(url, resource); -} - -ArchiveResource* ArchiveResourceCollection::archiveResourceForURL(const KURL& url) -{ - ArchiveResource* resource = m_subresources.get(url).get(); - if (!resource) - return 0; - - return resource; -} - -PassRefPtr<Archive> ArchiveResourceCollection::popSubframeArchive(const String& frameName) -{ - return m_subframes.take(frameName); -} - -} diff --git a/WebCore/loader/archive/ArchiveResourceCollection.h b/WebCore/loader/archive/ArchiveResourceCollection.h deleted file mode 100644 index f898a8d..0000000 --- a/WebCore/loader/archive/ArchiveResourceCollection.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ArchiveResourceCollection_h -#define ArchiveResourceCollection_h - -#include "Archive.h" -#include "ArchiveResource.h" -#include "KURL.h" -#include "PlatformString.h" - -#include <wtf/HashMap.h> -#include <wtf/RefCounted.h> - -namespace WebCore { - -class ArchiveResourceCollection : Noncopyable { -public: - ArchiveResourceCollection(); - - void addResource(PassRefPtr<ArchiveResource>); - void addAllResources(Archive*); - - ArchiveResource* archiveResourceForURL(const KURL&); - PassRefPtr<Archive> popSubframeArchive(const String& frameName); - -private: - HashMap<String, RefPtr<ArchiveResource> > m_subresources; - HashMap<String, RefPtr<Archive> > m_subframes; -}; - -} - -#endif diff --git a/WebCore/loader/archive/cf/LegacyWebArchive.cpp b/WebCore/loader/archive/cf/LegacyWebArchive.cpp deleted file mode 100644 index 9d99588..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchive.cpp +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LegacyWebArchive.h" - -#include "CString.h" -#include "Document.h" -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameTree.h" -#include "HTMLFrameOwnerElement.h" -#include "HTMLNames.h" -#include "KURL.h" -#include "Logging.h" -#include "markup.h" -#include "Node.h" -#include "Range.h" -#include "SelectionController.h" -#include "SharedBuffer.h" - -#include <wtf/RetainPtr.h> - -namespace WebCore { - -static const CFStringRef LegacyWebArchiveMainResourceKey = CFSTR("WebMainResource"); -static const CFStringRef LegacyWebArchiveSubresourcesKey = CFSTR("WebSubresources"); -static const CFStringRef LegacyWebArchiveSubframeArchivesKey = CFSTR("WebSubframeArchives"); -static const CFStringRef LegacyWebArchiveResourceDataKey = CFSTR("WebResourceData"); -static const CFStringRef LegacyWebArchiveResourceFrameNameKey = CFSTR("WebResourceFrameName"); -static const CFStringRef LegacyWebArchiveResourceMIMETypeKey = CFSTR("WebResourceMIMEType"); -static const CFStringRef LegacyWebArchiveResourceURLKey = CFSTR("WebResourceURL"); -static const CFStringRef LegacyWebArchiveResourceTextEncodingNameKey = CFSTR("WebResourceTextEncodingName"); -static const CFStringRef LegacyWebArchiveResourceResponseKey = CFSTR("WebResourceResponse"); -static const CFStringRef LegacyWebArchiveResourceResponseVersionKey = CFSTR("WebResourceResponseVersion"); - -static RetainPtr<CFDictionaryRef> createPropertyListRepresentationFromResource(ArchiveResource* resource, bool mainResource) -{ - if (!resource) { - // The property list representation of a null/empty WebResource has the following 3 objects stored as nil - RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, 0)); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, 0); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, 0); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, 0); - - return propertyList; - } - - RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 6, 0, &kCFTypeDictionaryValueCallBacks)); - - // Resource data can be empty, but must be represented by an empty CFDataRef - SharedBuffer* data = resource->data(); - RetainPtr<CFDataRef> cfData; - if (data) - cfData.adoptCF(data->createCFData()); - else - cfData.adoptCF(CFDataCreate(0, 0, 0)); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, cfData.get()); - - // Resource URL cannot be null - RetainPtr<CFStringRef> cfURL(AdoptCF, resource->url().string().createCFString()); - if (cfURL) - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, cfURL.get()); - else { - LOG(Archives, "LegacyWebArchive - NULL resource URL is invalid - returning null property list"); - return 0; - } - - // FrameName should be left out if empty for subresources, but always included for main resources - const String& frameName(resource->frameName()); - if (!frameName.isEmpty() || mainResource) { - RetainPtr<CFStringRef> cfFrameName(AdoptCF, frameName.createCFString()); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceFrameNameKey, cfFrameName.get()); - } - - // Set MIMEType, TextEncodingName, and ResourceResponse only if they actually exist - const String& mimeType(resource->mimeType()); - if (!mimeType.isEmpty()) { - RetainPtr<CFStringRef> cfMIMEType(AdoptCF, mimeType.createCFString()); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, cfMIMEType.get()); - } - - const String& textEncoding(resource->textEncoding()); - if (!textEncoding.isEmpty()) { - RetainPtr<CFStringRef> cfTextEncoding(AdoptCF, textEncoding.createCFString()); - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceTextEncodingNameKey, cfTextEncoding.get()); - } - - // Don't include the resource response for the main resource - if (!mainResource) { - RetainPtr<CFDataRef> resourceResponseData = propertyListDataFromResourceResponse(resource->response()); - if (resourceResponseData) - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceResponseKey, resourceResponseData.get()); - } - - return propertyList; -} - -static RetainPtr<CFDictionaryRef> createPropertyListRep(Archive* archive) -{ - RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, &kCFTypeDictionaryValueCallBacks)); - - RetainPtr<CFDictionaryRef> mainResourceDict = createPropertyListRepresentationFromResource(archive->mainResource(), true); - if (!mainResourceDict) - return 0; - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveMainResourceKey, mainResourceDict.get()); - - RetainPtr<CFMutableArrayRef> subresourcesArray(AdoptCF, CFArrayCreateMutable(0, archive->subresources().size(), &kCFTypeArrayCallBacks)); - const Vector<RefPtr<ArchiveResource> >& subresources(archive->subresources()); - for (unsigned i = 0; i < subresources.size(); ++i) { - RetainPtr<CFDictionaryRef> subresource = createPropertyListRepresentationFromResource(subresources[i].get(), false); - if (subresource) - CFArrayAppendValue(subresourcesArray.get(), subresource.get()); - else - LOG(Archives, "LegacyWebArchive - Failed to create property list for subresource"); - } - if (CFArrayGetCount(subresourcesArray.get())) - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubresourcesKey, subresourcesArray.get()); - - RetainPtr<CFMutableArrayRef> subframesArray(AdoptCF, CFArrayCreateMutable(0, archive->subframeArchives().size(), &kCFTypeArrayCallBacks)); - const Vector<RefPtr<Archive> >& subframeArchives(archive->subframeArchives()); - for (unsigned i = 0; i < subframeArchives.size(); ++i) { - RetainPtr<CFDictionaryRef> subframeArchive = createPropertyListRep(subframeArchives[i].get()); - if (subframeArchive) - CFArrayAppendValue(subframesArray.get(), subframeArchive.get()); - else - LOG(Archives, "LegacyWebArchive - Failed to create property list for subframe archive"); - } - if (CFArrayGetCount(subframesArray.get())) - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubframeArchivesKey, subframesArray.get()); - - return propertyList; -} - -static ResourceResponse createResourceResponseFromPropertyListData(CFDataRef data, CFStringRef responseDataType) -{ - ASSERT(data); - if (!data) - return ResourceResponse(); - - // If the ResourceResponseVersion (passed in as responseDataType) exists at all, this is a "new" webarchive that we can parse well in a cross platform manner - // If it doesn't exist, we will assume this is an "old" Cocoa-based WebArchive, and parse the ResourceResponse as such - if (!responseDataType) - return createResourceResponseFromMacArchivedData(data); - - // FIXME: Parse the "new" format that the above comment references here - return ResourceResponse(); -} - -static PassRefPtr<ArchiveResource> createResource(CFDictionaryRef dictionary) -{ - ASSERT(dictionary); - if (!dictionary) - return 0; - - CFDataRef resourceData = static_cast<CFDataRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceDataKey)); - if (resourceData && CFGetTypeID(resourceData) != CFDataGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Resource data is not of type CFData, cannot create invalid resource"); - return 0; - } - - CFStringRef frameName = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceFrameNameKey)); - if (frameName && CFGetTypeID(frameName) != CFStringGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Frame name is not of type CFString, cannot create invalid resource"); - return 0; - } - - CFStringRef mimeType = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceMIMETypeKey)); - if (mimeType && CFGetTypeID(mimeType) != CFStringGetTypeID()) { - LOG(Archives, "LegacyWebArchive - MIME type is not of type CFString, cannot create invalid resource"); - return 0; - } - - CFStringRef url = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceURLKey)); - if (url && CFGetTypeID(url) != CFStringGetTypeID()) { - LOG(Archives, "LegacyWebArchive - URL is not of type CFString, cannot create invalid resource"); - return 0; - } - - CFStringRef textEncoding = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceTextEncodingNameKey)); - if (textEncoding && CFGetTypeID(textEncoding) != CFStringGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Text encoding is not of type CFString, cannot create invalid resource"); - return 0; - } - - ResourceResponse response; - - CFDataRef resourceResponseData = static_cast<CFDataRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceResponseKey)); - if (resourceResponseData) { - if (CFGetTypeID(resourceResponseData) != CFDataGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Resource response data is not of type CFData, cannot create invalid resource"); - return 0; - } - - CFStringRef resourceResponseVersion = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceResponseVersionKey)); - if (resourceResponseVersion && CFGetTypeID(resourceResponseVersion) != CFStringGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Resource response version is not of type CFString, cannot create invalid resource"); - return 0; - } - - response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion); - } - - return ArchiveResource::create(SharedBuffer::create(CFDataGetBytePtr(resourceData), CFDataGetLength(resourceData)), KURL(url), mimeType, textEncoding, frameName, response); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create() -{ - return adoptRef(new LegacyWebArchive); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(SharedBuffer* data) -{ - LOG(Archives, "LegacyWebArchive - Creating from raw data"); - - RefPtr<LegacyWebArchive> archive = create(); - if (!archive->init(data)) - return 0; - - return archive.release(); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(PassRefPtr<ArchiveResource> mainResource, Vector<PassRefPtr<ArchiveResource> >& subresources, Vector<PassRefPtr<LegacyWebArchive> >& subframeArchives) -{ - ASSERT(mainResource); - if (!mainResource) - return 0; - - RefPtr<LegacyWebArchive> archive = create(); - archive->setMainResource(mainResource); - - for (unsigned i = 0; i < subresources.size(); ++i) - archive->addSubresource(subresources[i]); - - for (unsigned i = 0; i < subframeArchives.size(); ++i) - archive->addSubframeArchive(subframeArchives[i]); - - return archive.release(); -} - -LegacyWebArchive::LegacyWebArchive() -{ -} - -bool LegacyWebArchive::init(SharedBuffer* data) -{ - ASSERT(data); - if (!data) - return false; - - RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData()); - if (!cfData) - return false; - - CFStringRef errorString = 0; - - RetainPtr<CFDictionaryRef> plist(AdoptCF, static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(0, cfData.get(), kCFPropertyListImmutable, &errorString))); - if (!plist) { -#ifndef NDEBUG - const char* cError = errorString ? CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8) : "unknown error"; - LOG(Archives, "LegacyWebArchive - Error parsing PropertyList from archive data - %s", cError); -#endif - if (errorString) - CFRelease(errorString); - return false; - } - - if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Archive property list is not the expected CFDictionary, aborting invalid WebArchive"); - return false; - } - - return extract(plist.get()); -} - -bool LegacyWebArchive::extract(CFDictionaryRef dictionary) -{ - ASSERT(dictionary); - if (!dictionary) { - LOG(Archives, "LegacyWebArchive - Null root CFDictionary, aborting invalid WebArchive"); - return false; - } - - CFDictionaryRef mainResourceDict = static_cast<CFDictionaryRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveMainResourceKey)); - if (!mainResourceDict) { - LOG(Archives, "LegacyWebArchive - No main resource in archive, aborting invalid WebArchive"); - return false; - } - if (CFGetTypeID(mainResourceDict) != CFDictionaryGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Main resource is not the expected CFDictionary, aborting invalid WebArchive"); - return false; - } - - setMainResource(createResource(mainResourceDict)); - if (!mainResource()) { - LOG(Archives, "LegacyWebArchive - Failed to parse main resource from CFDictionary or main resource does not exist, aborting invalid WebArchive"); - return false; - } - - CFArrayRef subresourceArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubresourcesKey)); - if (subresourceArray && CFGetTypeID(subresourceArray) != CFArrayGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Subresources is not the expected Array, aborting invalid WebArchive"); - return false; - } - - if (subresourceArray) { - CFIndex count = CFArrayGetCount(subresourceArray); - for (CFIndex i = 0; i < count; ++i) { - CFDictionaryRef subresourceDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subresourceArray, i)); - if (CFGetTypeID(subresourceDict) != CFDictionaryGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Subresource is not expected CFDictionary, aborting invalid WebArchive"); - return false; - } - addSubresource(createResource(subresourceDict)); - } - } - - CFArrayRef subframeArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubframeArchivesKey)); - if (subframeArray && CFGetTypeID(subframeArray) != CFArrayGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Subframe archives is not the expected Array, aborting invalid WebArchive"); - return false; - } - - if (subframeArray) { - CFIndex count = CFArrayGetCount(subframeArray); - for (CFIndex i = 0; i < count; ++i) { - CFDictionaryRef subframeDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subframeArray, i)); - if (CFGetTypeID(subframeDict) != CFDictionaryGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Subframe array is not expected CFDictionary, aborting invalid WebArchive"); - return false; - } - - RefPtr<LegacyWebArchive> subframeArchive = create(); - if (subframeArchive->extract(subframeDict)) - addSubframeArchive(subframeArchive.release()); - else - LOG(Archives, "LegacyWebArchive - Invalid subframe archive skipped"); - } - } - - return true; -} - -RetainPtr<CFDataRef> LegacyWebArchive::rawDataRepresentation() -{ - RetainPtr<CFDictionaryRef> propertyList = createPropertyListRep(this); - if (!propertyList) { - LOG(Archives, "LegacyWebArchive - Failed to create property list for archive, returning no data"); - return 0; - } - - // FIXME: On Mac, WebArchives have been written out as Binary Property Lists until this change. - // Unless we jump through CFWriteStream hoops, they'll now be textual XML data. Is this okay? - RetainPtr<CFDataRef> plistData(AdoptCF, CFPropertyListCreateXMLData(0, propertyList.get())); - if (!plistData) { - LOG(Archives, "LegacyWebArchive - Failed to convert property list into raw data, returning no data"); - return 0; - } - - return plistData; -} - -#if !PLATFORM(MAC) -// FIXME: Is it possible to parse in a Cocoa-style resource response manually, -// without NSKeyed(Un)Archiver, manipulating plists directly? -// If so, the code that does it will go here. -// In the meantime, Mac will continue to NSKeyed(Un)Archive the response as it always has -ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef responseData) -{ - return ResourceResponse(); -} - -RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse& response) -{ - // FIXME: Write out the "new" format described in ::createResourceResponseFromPropertyListData() up above - return 0; -} -#endif - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Node* node) -{ - ASSERT(node); - if (!node) - return create(); - - Document* document = node->document(); - Frame* frame = document ? document->frame() : 0; - if (!frame) - return create(); - - Vector<Node*> nodeList; - String markupString = createMarkup(node, IncludeNode, &nodeList); - Node::NodeType nodeType = node->nodeType(); - if (nodeType != Node::DOCUMENT_NODE && nodeType != Node::DOCUMENT_TYPE_NODE) - markupString = frame->documentTypeString() + markupString; - - return create(markupString, frame, nodeList); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Frame* frame) -{ - ASSERT(frame); - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - - if (!documentLoader) - return 0; - - Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; - - unsigned children = frame->tree()->childCount(); - for (unsigned i = 0; i < children; ++i) { - RefPtr<LegacyWebArchive> childFrameArchive = create(frame->tree()->child(i)); - if (childFrameArchive) - subframeArchives.append(childFrameArchive.release()); - } - - Vector<PassRefPtr<ArchiveResource> > subresources; - documentLoader->getSubresources(subresources); - - return LegacyWebArchive::create(documentLoader->mainResource(), subresources, subframeArchives); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Range* range) -{ - if (!range) - return 0; - - Node* startContainer = range->startContainer(); - if (!startContainer) - return 0; - - Document* document = startContainer->document(); - if (!document) - return 0; - - Frame* frame = document->frame(); - if (!frame) - return 0; - - Vector<Node*> nodeList; - - // FIXME: This is always "for interchange". Is that right? See the previous method. - String markupString = frame->documentTypeString() + createMarkup(range, &nodeList, AnnotateForInterchange); - - return create(markupString, frame, nodeList); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame* frame, Vector<Node*>& nodes) -{ - ASSERT(frame); - - const ResourceResponse& response = frame->loader()->documentLoader()->response(); - KURL responseURL = response.url(); - - // it's possible to have a response without a URL here - // <rdar://problem/5454935> - if (responseURL.isNull()) - responseURL = KURL(""); - - PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->name()); - - Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; - Vector<PassRefPtr<ArchiveResource> > subresources; - HashSet<String> uniqueSubresources; - - Vector<Node*>::iterator it = nodes.begin(); - Vector<Node*>::iterator end = nodes.end(); - - for (; it != end; ++it) { - Frame* childFrame; - if (((*it)->hasTagName(HTMLNames::frameTag) || (*it)->hasTagName(HTMLNames::iframeTag) || (*it)->hasTagName(HTMLNames::objectTag)) && - (childFrame = static_cast<HTMLFrameOwnerElement*>(*it)->contentFrame())) { - RefPtr<LegacyWebArchive> subframeArchive; - if (Document* document = childFrame->document()) - subframeArchive = LegacyWebArchive::create(document); - else - subframeArchive = create(childFrame); - - if (subframeArchive) - subframeArchives.append(subframeArchive); - else - LOG_ERROR("Unabled to archive subframe %s", childFrame->tree()->name().string().utf8().data()); - } else { - Vector<KURL> subresourceURLs; - (*it)->getSubresourceURLs(subresourceURLs); - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - for (unsigned i = 0; i < subresourceURLs.size(); ++i) { - if (uniqueSubresources.contains(subresourceURLs[i].string())) - continue; - uniqueSubresources.add(subresourceURLs[i].string()); - RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURLs[i]); - if (resource) - subresources.append(resource.release()); - else - // FIXME: should do something better than spew to console here - LOG_ERROR("Failed to archive subresource for %s", subresourceURLs[i].string().utf8().data()); - } - } - } - - return create(mainResource, subresources, subframeArchives); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::createFromSelection(Frame* frame) -{ - if (!frame) - return 0; - - RefPtr<Range> selectionRange = frame->selection()->toRange(); - Vector<Node*> nodeList; - String markupString = frame->documentTypeString() + createMarkup(selectionRange.get(), &nodeList, AnnotateForInterchange); - - RefPtr<LegacyWebArchive> archive = create(markupString, frame, nodeList); - - if (!frame->isFrameSet()) - return archive.release(); - - // Wrap the frameset document in an iframe so it can be pasted into - // another document (which will have a body or frameset of its own). - String iframeMarkup = String::format("<iframe frameborder=\"no\" marginwidth=\"0\" marginheight=\"0\" width=\"98%%\" height=\"98%%\" src=\"%s\"></iframe>", - frame->loader()->documentLoader()->response().url().string().utf8().data()); - RefPtr<ArchiveResource> iframeResource = ArchiveResource::create(utf8Buffer(iframeMarkup), blankURL(), "text/html", "UTF-8", String()); - - Vector<PassRefPtr<ArchiveResource> > subresources; - - Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; - subframeArchives.append(archive); - - archive = LegacyWebArchive::create(iframeResource.release(), subresources, subframeArchives); - - return archive.release(); -} - -} diff --git a/WebCore/loader/archive/cf/LegacyWebArchive.h b/WebCore/loader/archive/cf/LegacyWebArchive.h deleted file mode 100644 index 70faba5..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchive.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LegacyWebArchive_h -#define LegacyWebArchive_h - -#include "Archive.h" - -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -class Frame; -class Node; -class Range; - -class LegacyWebArchive : public Archive { -public: - static PassRefPtr<LegacyWebArchive> create(); - static PassRefPtr<LegacyWebArchive> create(SharedBuffer*); - static PassRefPtr<LegacyWebArchive> create(PassRefPtr<ArchiveResource> mainResource, Vector<PassRefPtr<ArchiveResource> >& subresources, Vector<PassRefPtr<LegacyWebArchive> >& subframeArchives); - static PassRefPtr<LegacyWebArchive> create(Node*); - static PassRefPtr<LegacyWebArchive> create(Frame*); - static PassRefPtr<LegacyWebArchive> createFromSelection(Frame* frame); - static PassRefPtr<LegacyWebArchive> create(Range*); - static PassRefPtr<LegacyWebArchive> create(const String& markupString, Frame*, Vector<Node*>& nodes); - - RetainPtr<CFDataRef> rawDataRepresentation(); - -private: - LegacyWebArchive(); - bool init(SharedBuffer*); - bool extract(CFDictionaryRef); - -}; - -ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef); -RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse&); - -} - -#endif // Archive diff --git a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm b/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm deleted file mode 100644 index b853a15..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LegacyWebArchive.h" - -namespace WebCore { - -static const NSString *LegacyWebArchiveResourceResponseKey = @"WebResourceResponse"; - -// FIXME: Is it possible to parse in a Cocoa-style resource response manually, -// without NSKeyed(Un)Archiver, manipulating plists directly? -ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef responseData) -{ - ASSERT(responseData); - if (!responseData) - return ResourceResponse(); - - NSURLResponse *response = nil; - NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)responseData]; - @try { - id responseObject = [unarchiver decodeObjectForKey:LegacyWebArchiveResourceResponseKey]; - if ([responseObject isKindOfClass:[NSURLResponse class]]) - response = responseObject; - [unarchiver finishDecoding]; - } @catch(id) { - response = nil; - } - [unarchiver release]; - - return ResourceResponse(response); -} - -RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse& response) -{ - NSURLResponse *nsResponse = response.nsURLResponse(); - if (!nsResponse) - return 0; - - NSMutableData *responseData = (NSMutableData *)CFDataCreateMutable(0, 0); - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:responseData]; - [archiver encodeObject:nsResponse forKey:LegacyWebArchiveResourceResponseKey]; - [archiver finishEncoding]; - [archiver release]; - - return RetainPtr<CFDataRef>(AdoptCF, (CFDataRef)responseData); -} - -} diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp deleted file mode 100644 index 72e57fe..0000000 --- a/WebCore/loader/icon/IconDatabase.cpp +++ /dev/null @@ -1,2053 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconDatabase.h" - -#include "AutodrainedPool.h" -#include "CString.h" -#include "DocumentLoader.h" -#include "FileSystem.h" -#include "IconDatabaseClient.h" -#include "IconRecord.h" -#include "Image.h" -#include "IntSize.h" -#include "KURL.h" -#include "Logging.h" -#include "PageURLRecord.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" -#include "SystemTime.h" -#include <runtime/InitializeThreading.h> -#include <wtf/MainThread.h> - -#if PLATFORM(WIN_OS) -#include <windows.h> -#include <winbase.h> -#include <shlobj.h> -#else -#include <sys/stat.h> -#endif - -#if PLATFORM(DARWIN) -#include <pthread.h> -#endif - -#include <errno.h> - -// For methods that are meant to support API from the main thread - should not be called internally -#define ASSERT_NOT_SYNC_THREAD() ASSERT(!m_syncThreadRunning || !IS_ICON_SYNC_THREAD()) - -// For methods that are meant to support the sync thread ONLY -#define IS_ICON_SYNC_THREAD() (m_syncThread == currentThread()) -#define ASSERT_ICON_SYNC_THREAD() ASSERT(IS_ICON_SYNC_THREAD()) - -#if PLATFORM(QT) -#define CAN_THEME_URL_ICON -#endif - -namespace WebCore { - -static IconDatabase* sharedIconDatabase = 0; -static int databaseCleanupCounter = 0; - -// This version number is in the DB and marks the current generation of the schema -// Currently, a mismatched schema causes the DB to be wiped and reset. This isn't -// so bad during development but in the future, we would need to write a conversion -// function to advance older released schemas to "current" -const int currentDatabaseVersion = 6; - -// Icons expire once every 4 days -const int iconExpirationTime = 60*60*24*4; - -const int updateTimerDelay = 5; - -static bool checkIntegrityOnOpen = false; - -#ifndef NDEBUG -static String urlForLogging(const String& url) -{ - static unsigned urlTruncationLength = 120; - - if (url.length() < urlTruncationLength) - return url; - return url.substring(0, urlTruncationLength) + "..."; -} -#endif - -static IconDatabaseClient* defaultClient() -{ - static IconDatabaseClient* defaultClient = new IconDatabaseClient(); - return defaultClient; -} - -IconDatabase* iconDatabase() -{ - if (!sharedIconDatabase) { - JSC::initializeThreading(); - sharedIconDatabase = new IconDatabase; - } - return sharedIconDatabase; -} - -// ************************ -// *** Main Thread Only *** -// ************************ - -void IconDatabase::setClient(IconDatabaseClient* client) -{ - // We don't allow a null client, because we never null check it anywhere in this code - // Also don't allow a client change after the thread has already began - // (setting the client should occur before the database is opened) - ASSERT(client); - ASSERT(!m_syncThreadRunning); - if (!client || m_syncThreadRunning) - return; - - m_client = client; -} - -bool IconDatabase::open(const String& databasePath) -{ - ASSERT_NOT_SYNC_THREAD(); - - if (!m_isEnabled) - return false; - - if (isOpen()) { - LOG_ERROR("Attempt to reopen the IconDatabase which is already open. Must close it first."); - return false; - } - - m_databaseDirectory = databasePath.copy(); - - // Formulate the full path for the database file - m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, defaultDatabaseFilename()); - - // Lock here as well as first thing in the thread so the thread doesn't actually commence until the createThread() call - // completes and m_syncThreadRunning is properly set - m_syncLock.lock(); - m_syncThread = createThread(IconDatabase::iconDatabaseSyncThreadStart, this, "WebCore::IconDatabase"); - m_syncLock.unlock(); - if (!m_syncThread) - return false; - return true; -} - -void IconDatabase::close() -{ -#ifdef ANDROID - // Since we close and reopen the database within the same process, reset - // this flag - m_initialPruningComplete = false; -#endif - ASSERT_NOT_SYNC_THREAD(); - - if (m_syncThreadRunning) { - // Set the flag to tell the sync thread to wrap it up - m_threadTerminationRequested = true; - - // Wake up the sync thread if it's waiting - wakeSyncThread(); - - // Wait for the sync thread to terminate - waitForThreadCompletion(m_syncThread, 0); - } - - m_syncThreadRunning = false; - m_threadTerminationRequested = false; - m_removeIconsRequested = false; -} - -void IconDatabase::removeAllIcons() -{ - ASSERT_NOT_SYNC_THREAD(); - - if (!isOpen()) - return; - - LOG(IconDatabase, "Requesting background thread to remove all icons"); - - // Clear the in-memory record of every IconRecord, anything waiting to be read from disk, and anything waiting to be written to disk - { - MutexLocker locker(m_urlAndIconLock); - - // Clear the IconRecords for every page URL - RefCounting will cause the IconRecords themselves to be deleted - // We don't delete the actual PageRecords because we have the "retain icon for url" count to keep track of - HashMap<String, PageURLRecord*>::iterator iter = m_pageURLToRecordMap.begin(); - HashMap<String, PageURLRecord*>::iterator end = m_pageURLToRecordMap.end(); - for (; iter != end; ++iter) - (*iter).second->setIconRecord(0); - - // Clear the iconURL -> IconRecord map - m_iconURLToRecordMap.clear(); - - // Clear all in-memory records of things that need to be synced out to disk - { - MutexLocker locker(m_pendingSyncLock); - m_pageURLsPendingSync.clear(); - m_iconsPendingSync.clear(); - } - - // Clear all in-memory records of things that need to be read in from disk - { - MutexLocker locker(m_pendingReadingLock); - m_pageURLsPendingImport.clear(); - m_pageURLsInterestedInIcons.clear(); - m_iconsPendingReading.clear(); - m_loadersPendingDecision.clear(); - } - } - - m_removeIconsRequested = true; - wakeSyncThread(); -} - -Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize& size) -{ - ASSERT_NOT_SYNC_THREAD(); - - // pageURLOriginal cannot be stored without being deep copied first. - // We should go our of our way to only copy it if we have to store it - - if (!isOpen() || pageURLOriginal.isEmpty()) - return defaultIcon(size); - - MutexLocker locker(m_urlAndIconLock); - - String pageURLCopy; // Creates a null string for easy testing - - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal); - if (!pageRecord) { - pageURLCopy = pageURLOriginal.copy(); - pageRecord = getOrCreatePageURLRecord(pageURLCopy); - } - - // If pageRecord is NULL, one of two things is true - - // 1 - The initial url import is incomplete and this pageURL was marked to be notified once it is complete if an iconURL exists - // 2 - The initial url import IS complete and this pageURL has no icon - if (!pageRecord) { - MutexLocker locker(m_pendingReadingLock); - - // Import is ongoing, there might be an icon. In this case, register to be notified when the icon comes in - // If we ever reach this condition, we know we've already made the pageURL copy - if (!m_iconURLImportComplete) - m_pageURLsInterestedInIcons.add(pageURLCopy); - - return 0; - } - - IconRecord* iconRecord = pageRecord->iconRecord(); - - // If the initial URL import isn't complete, it's possible to have a PageURL record without an associated icon - // In this case, the pageURL is already in the set to alert the client when the iconURL mapping is complete so - // we can just bail now - if (!m_iconURLImportComplete && !iconRecord) - return 0; - - // The only way we should *not* have an icon record is if this pageURL is retained but has no icon yet - make sure of that - ASSERT(iconRecord || m_retainedPageURLs.contains(pageURLOriginal)); - - if (!iconRecord) - return 0; - - // If it's a new IconRecord object that doesn't have its imageData set yet, - // mark it to be read by the background thread - if (iconRecord->imageDataStatus() == ImageDataStatusUnknown) { - if (pageURLCopy.isNull()) - pageURLCopy = pageURLOriginal.copy(); - - MutexLocker locker(m_pendingReadingLock); - m_pageURLsInterestedInIcons.add(pageURLCopy); - m_iconsPendingReading.add(iconRecord); - wakeSyncThread(); - return 0; - } - - // If the size parameter was (0, 0) that means the caller of this method just wanted the read from disk to be kicked off - // and isn't actually interested in the image return value - if (size == IntSize(0, 0)) - return 0; - - // PARANOID DISCUSSION: This method makes some assumptions. It returns a WebCore::image which the icon database might dispose of at anytime in the future, - // and Images aren't ref counted. So there is no way for the client to guarantee continued existence of the image. - // This has *always* been the case, but in practice clients would always create some other platform specific representation of the image - // and drop the raw Image*. On Mac an NSImage, and on windows drawing into an HBITMAP. - // The async aspect adds a huge question - what if the image is deleted before the platform specific API has a chance to create its own - // representation out of it? - // If an image is read in from the icondatabase, we do *not* overwrite any image data that exists in the in-memory cache. - // This is because we make the assumption that anything in memory is newer than whatever is in the database. - // So the only time the data will be set from the second thread is when it is INITIALLY being read in from the database, but we would never - // delete the image on the secondary thread if the image already exists. - return iconRecord->image(size); -} - -void IconDatabase::readIconForPageURLFromDisk(const String& pageURL) -{ - // The effect of asking for an Icon for a pageURL automatically queues it to be read from disk - // if it hasn't already been set in memory. The special IntSize (0, 0) is a special way of telling - // that method "I don't care about the actual Image, i just want you to make sure you're getting it from disk. - iconForPageURL(pageURL, IntSize(0,0)); -} - -String IconDatabase::iconURLForPageURL(const String& pageURLOriginal) -{ - ASSERT_NOT_SYNC_THREAD(); - - // Cannot do anything with pageURLOriginal that would end up storing it without deep copying first - // Also, in the case we have a real answer for the caller, we must deep copy that as well - - if (!isOpen() || pageURLOriginal.isEmpty()) - return String(); - - MutexLocker locker(m_urlAndIconLock); - - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal); - if (!pageRecord) - pageRecord = getOrCreatePageURLRecord(pageURLOriginal.copy()); - - // If pageRecord is NULL, one of two things is true - - // 1 - The initial url import is incomplete and this pageURL has already been marked to be notified once it is complete if an iconURL exists - // 2 - The initial url import IS complete and this pageURL has no icon - if (!pageRecord) - return String(); - - // Possible the pageRecord is around because it's a retained pageURL with no iconURL, so we have to check - return pageRecord->iconRecord() ? pageRecord->iconRecord()->iconURL().copy() : String(); -} - -#ifdef CAN_THEME_URL_ICON -static inline void loadDefaultIconRecord(IconRecord* defaultIconRecord) -{ - defaultIconRecord->loadImageFromResource("urlIcon"); -} -#else -static inline void loadDefaultIconRecord(IconRecord* defaultIconRecord) -{ - static const unsigned char defaultIconData[] = { 0x4D, 0x4D, 0x00, 0x2A, 0x00, 0x00, 0x03, 0x32, 0x80, 0x00, 0x20, 0x50, 0x38, 0x24, 0x16, 0x0D, 0x07, 0x84, 0x42, 0x61, 0x50, 0xB8, - 0x64, 0x08, 0x18, 0x0D, 0x0A, 0x0B, 0x84, 0xA2, 0xA1, 0xE2, 0x08, 0x5E, 0x39, 0x28, 0xAF, 0x48, 0x24, 0xD3, 0x53, 0x9A, 0x37, 0x1D, 0x18, 0x0E, 0x8A, 0x4B, 0xD1, 0x38, - 0xB0, 0x7C, 0x82, 0x07, 0x03, 0x82, 0xA2, 0xE8, 0x6C, 0x2C, 0x03, 0x2F, 0x02, 0x82, 0x41, 0xA1, 0xE2, 0xF8, 0xC8, 0x84, 0x68, 0x6D, 0x1C, 0x11, 0x0A, 0xB7, 0xFA, 0x91, - 0x6E, 0xD1, 0x7F, 0xAF, 0x9A, 0x4E, 0x87, 0xFB, 0x19, 0xB0, 0xEA, 0x7F, 0xA4, 0x95, 0x8C, 0xB7, 0xF9, 0xA9, 0x0A, 0xA9, 0x7F, 0x8C, 0x88, 0x66, 0x96, 0xD4, 0xCA, 0x69, - 0x2F, 0x00, 0x81, 0x65, 0xB0, 0x29, 0x90, 0x7C, 0xBA, 0x2B, 0x21, 0x1E, 0x5C, 0xE6, 0xB4, 0xBD, 0x31, 0xB6, 0xE7, 0x7A, 0xBF, 0xDD, 0x6F, 0x37, 0xD3, 0xFD, 0xD8, 0xF2, - 0xB6, 0xDB, 0xED, 0xAC, 0xF7, 0x03, 0xC5, 0xFE, 0x77, 0x53, 0xB6, 0x1F, 0xE6, 0x24, 0x8B, 0x1D, 0xFE, 0x26, 0x20, 0x9E, 0x1C, 0xE0, 0x80, 0x65, 0x7A, 0x18, 0x02, 0x01, - 0x82, 0xC5, 0xA0, 0xC0, 0xF1, 0x89, 0xBA, 0x23, 0x30, 0xAD, 0x1F, 0xE7, 0xE5, 0x5B, 0x6D, 0xFE, 0xE7, 0x78, 0x3E, 0x1F, 0xEE, 0x97, 0x8B, 0xE7, 0x37, 0x9D, 0xCF, 0xE7, - 0x92, 0x8B, 0x87, 0x0B, 0xFC, 0xA0, 0x8E, 0x68, 0x3F, 0xC6, 0x27, 0xA6, 0x33, 0xFC, 0x36, 0x5B, 0x59, 0x3F, 0xC1, 0x02, 0x63, 0x3B, 0x74, 0x00, 0x03, 0x07, 0x0B, 0x61, - 0x00, 0x20, 0x60, 0xC9, 0x08, 0x00, 0x1C, 0x25, 0x9F, 0xE0, 0x12, 0x8A, 0xD5, 0xFE, 0x6B, 0x4F, 0x35, 0x9F, 0xED, 0xD7, 0x4B, 0xD9, 0xFE, 0x8A, 0x59, 0xB8, 0x1F, 0xEC, - 0x56, 0xD3, 0xC1, 0xFE, 0x63, 0x4D, 0xF2, 0x83, 0xC6, 0xB6, 0x1B, 0xFC, 0x34, 0x68, 0x61, 0x3F, 0xC1, 0xA6, 0x25, 0xEB, 0xFC, 0x06, 0x58, 0x5C, 0x3F, 0xC0, 0x03, 0xE4, - 0xC3, 0xFC, 0x04, 0x0F, 0x1A, 0x6F, 0xE0, 0xE0, 0x20, 0xF9, 0x61, 0x7A, 0x02, 0x28, 0x2B, 0xBC, 0x46, 0x25, 0xF3, 0xFC, 0x66, 0x3D, 0x99, 0x27, 0xF9, 0x7E, 0x6B, 0x1D, - 0xC7, 0xF9, 0x2C, 0x5E, 0x1C, 0x87, 0xF8, 0xC0, 0x4D, 0x9A, 0xE7, 0xF8, 0xDA, 0x51, 0xB2, 0xC1, 0x68, 0xF2, 0x64, 0x1F, 0xE1, 0x50, 0xED, 0x0A, 0x04, 0x23, 0x79, 0x8A, - 0x7F, 0x82, 0xA3, 0x39, 0x80, 0x7F, 0x80, 0xC2, 0xB1, 0x5E, 0xF7, 0x04, 0x2F, 0xB2, 0x10, 0x02, 0x86, 0x63, 0xC9, 0xCC, 0x07, 0xBF, 0x87, 0xF8, 0x4A, 0x38, 0xAF, 0xC1, - 0x88, 0xF8, 0x66, 0x1F, 0xE1, 0xD9, 0x08, 0xD4, 0x8F, 0x25, 0x5B, 0x4A, 0x49, 0x97, 0x87, 0x39, 0xFE, 0x25, 0x12, 0x10, 0x68, 0xAA, 0x4A, 0x2F, 0x42, 0x29, 0x12, 0x69, - 0x9F, 0xE1, 0xC1, 0x00, 0x67, 0x1F, 0xE1, 0x58, 0xED, 0x00, 0x83, 0x23, 0x49, 0x82, 0x7F, 0x81, 0x21, 0xE0, 0xFC, 0x73, 0x21, 0x00, 0x50, 0x7D, 0x2B, 0x84, 0x03, 0x83, - 0xC2, 0x1B, 0x90, 0x06, 0x69, 0xFE, 0x23, 0x91, 0xAE, 0x50, 0x9A, 0x49, 0x32, 0xC2, 0x89, 0x30, 0xE9, 0x0A, 0xC4, 0xD9, 0xC4, 0x7F, 0x94, 0xA6, 0x51, 0xDE, 0x7F, 0x9D, - 0x07, 0x89, 0xF6, 0x7F, 0x91, 0x85, 0xCA, 0x88, 0x25, 0x11, 0xEE, 0x50, 0x7C, 0x43, 0x35, 0x21, 0x60, 0xF1, 0x0D, 0x82, 0x62, 0x39, 0x07, 0x2C, 0x20, 0xE0, 0x80, 0x72, - 0x34, 0x17, 0xA1, 0x80, 0xEE, 0xF0, 0x89, 0x24, 0x74, 0x1A, 0x2C, 0x93, 0xB3, 0x78, 0xCC, 0x52, 0x9D, 0x6A, 0x69, 0x56, 0xBB, 0x0D, 0x85, 0x69, 0xE6, 0x7F, 0x9E, 0x27, - 0xB9, 0xFD, 0x50, 0x54, 0x47, 0xF9, 0xCC, 0x78, 0x9F, 0x87, 0xF9, 0x98, 0x70, 0xB9, 0xC2, 0x91, 0x2C, 0x6D, 0x1F, 0xE1, 0xE1, 0x00, 0xBF, 0x02, 0xC1, 0xF5, 0x18, 0x84, - 0x01, 0xE1, 0x48, 0x8C, 0x42, 0x07, 0x43, 0xC9, 0x76, 0x7F, 0x8B, 0x04, 0xE4, 0xDE, 0x35, 0x95, 0xAB, 0xB0, 0xF0, 0x5C, 0x55, 0x23, 0xF9, 0x7E, 0x7E, 0x9F, 0xE4, 0x0C, - 0xA7, 0x55, 0x47, 0xC7, 0xF9, 0xE6, 0xCF, 0x1F, 0xE7, 0x93, 0x35, 0x52, 0x54, 0x63, 0x19, 0x46, 0x73, 0x1F, 0xE2, 0x61, 0x08, 0xF0, 0x82, 0xE1, 0x80, 0x92, 0xF9, 0x20, - 0xC0, 0x28, 0x18, 0x0A, 0x05, 0xA1, 0xA2, 0xF8, 0x6E, 0xDB, 0x47, 0x49, 0xFE, 0x3E, 0x17, 0xB6, 0x61, 0x13, 0x1A, 0x29, 0x26, 0xA9, 0xFE, 0x7F, 0x92, 0x70, 0x69, 0xFE, - 0x4C, 0x2F, 0x55, 0x01, 0xF1, 0x54, 0xD4, 0x35, 0x49, 0x4A, 0x69, 0x59, 0x83, 0x81, 0x58, 0x76, 0x9F, 0xE2, 0x20, 0xD6, 0x4C, 0x9B, 0xA0, 0x48, 0x1E, 0x0B, 0xB7, 0x48, - 0x58, 0x26, 0x11, 0x06, 0x42, 0xE8, 0xA4, 0x40, 0x17, 0x27, 0x39, 0x00, 0x60, 0x2D, 0xA4, 0xC3, 0x2C, 0x7F, 0x94, 0x56, 0xE4, 0xE1, 0x77, 0x1F, 0xE5, 0xB9, 0xD7, 0x66, - 0x1E, 0x07, 0xB3, 0x3C, 0x63, 0x1D, 0x35, 0x49, 0x0E, 0x63, 0x2D, 0xA2, 0xF1, 0x12, 0x60, 0x1C, 0xE0, 0xE0, 0x52, 0x1B, 0x8B, 0xAC, 0x38, 0x0E, 0x07, 0x03, 0x60, 0x28, - 0x1C, 0x0E, 0x87, 0x00, 0xF0, 0x66, 0x27, 0x11, 0xA2, 0xC1, 0x02, 0x5A, 0x1C, 0xE4, 0x21, 0x83, 0x1F, 0x13, 0x86, 0xFA, 0xD2, 0x55, 0x1D, 0xD6, 0x61, 0xBC, 0x77, 0xD3, - 0xE6, 0x91, 0xCB, 0x4C, 0x90, 0xA6, 0x25, 0xB8, 0x2F, 0x90, 0xC5, 0xA9, 0xCE, 0x12, 0x07, 0x02, 0x91, 0x1B, 0x9F, 0x68, 0x00, 0x16, 0x76, 0x0D, 0xA1, 0x00, 0x08, 0x06, - 0x03, 0x81, 0xA0, 0x20, 0x1A, 0x0D, 0x06, 0x80, 0x30, 0x24, 0x12, 0x89, 0x20, 0x98, 0x4A, 0x1F, 0x0F, 0x21, 0xA0, 0x9E, 0x36, 0x16, 0xC2, 0x88, 0xE6, 0x48, 0x9B, 0x83, - 0x31, 0x1C, 0x55, 0x1E, 0x43, 0x59, 0x1A, 0x56, 0x1E, 0x42, 0xF0, 0xFA, 0x4D, 0x1B, 0x9B, 0x08, 0xDC, 0x5B, 0x02, 0xA1, 0x30, 0x7E, 0x3C, 0xEE, 0x5B, 0xA6, 0xDD, 0xB8, - 0x6D, 0x5B, 0x62, 0xB7, 0xCD, 0xF3, 0x9C, 0xEA, 0x04, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0xE0, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x01, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x11, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x08, 0x01, 0x15, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x01, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x17, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x29, 0x01, 0x1A, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xE8, 0x01, 0x1B, 0x00, 0x05, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x03, 0xF0, 0x01, 0x1C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x52, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, - 0xFC, 0x80, 0x00, 0x00, 0x27, 0x10, 0x00, 0x0A, 0xFC, 0x80, 0x00, 0x00, 0x27, 0x10 }; - - static RefPtr<SharedBuffer> defaultIconBuffer(SharedBuffer::create(defaultIconData, sizeof(defaultIconData))); - defaultIconRecord->setImageData(defaultIconBuffer); -} -#endif - -Image* IconDatabase::defaultIcon(const IntSize& size) -{ - ASSERT_NOT_SYNC_THREAD(); - - - if (!m_defaultIconRecord) { - m_defaultIconRecord = IconRecord::create("urlIcon"); - loadDefaultIconRecord(m_defaultIconRecord.get()); - } - - return m_defaultIconRecord->image(size); -} - - -void IconDatabase::retainIconForPageURL(const String& pageURLOriginal) -{ - ASSERT_NOT_SYNC_THREAD(); - - // Cannot do anything with pageURLOriginal that would end up storing it without deep copying first - - if (!isEnabled() || pageURLOriginal.isEmpty()) - return; - - MutexLocker locker(m_urlAndIconLock); - - PageURLRecord* record = m_pageURLToRecordMap.get(pageURLOriginal); - - String pageURL; - - if (!record) { - pageURL = pageURLOriginal.copy(); - - record = new PageURLRecord(pageURL); - m_pageURLToRecordMap.set(pageURL, record); - } - - if (!record->retain()) { - if (pageURL.isNull()) - pageURL = pageURLOriginal.copy(); - - // This page just had its retain count bumped from 0 to 1 - Record that fact - m_retainedPageURLs.add(pageURL); - - // If we read the iconURLs yet, we want to avoid any pageURL->iconURL lookups and the pageURLsPendingDeletion is moot, - // so we bail here and skip those steps - if (!m_iconURLImportComplete) - return; - - MutexLocker locker(m_pendingSyncLock); - // If this pageURL waiting to be sync'ed, update the sync record - // This saves us in the case where a page was ready to be deleted from the database but was just retained - so theres no need to delete it! - if (!m_privateBrowsingEnabled && m_pageURLsPendingSync.contains(pageURL)) { - LOG(IconDatabase, "Bringing %s back from the brink", pageURL.ascii().data()); - m_pageURLsPendingSync.set(pageURL, record->snapshot()); - } - } -} - -void IconDatabase::releaseIconForPageURL(const String& pageURLOriginal) -{ - ASSERT_NOT_SYNC_THREAD(); - - // Cannot do anything with pageURLOriginal that would end up storing it without deep copying first - - if (!isEnabled() || pageURLOriginal.isEmpty()) - return; - - MutexLocker locker(m_urlAndIconLock); - - // Check if this pageURL is actually retained - if (!m_retainedPageURLs.contains(pageURLOriginal)) { - LOG_ERROR("Attempting to release icon for URL %s which is not retained", urlForLogging(pageURLOriginal).ascii().data()); - return; - } - - // Get its retain count - if it's retained, we'd better have a PageURLRecord for it - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal); - ASSERT(pageRecord); - LOG(IconDatabase, "Releasing pageURL %s to a retain count of %i", urlForLogging(pageURLOriginal).ascii().data(), pageRecord->retainCount() - 1); - ASSERT(pageRecord->retainCount() > 0); - - // If it still has a positive retain count, store the new count and bail - if (pageRecord->release()) - return; - - // This pageRecord has now been fully released. Do the appropriate cleanup - LOG(IconDatabase, "No more retainers for PageURL %s", urlForLogging(pageURLOriginal).ascii().data()); - m_pageURLToRecordMap.remove(pageURLOriginal); - m_retainedPageURLs.remove(pageURLOriginal); - - // Grab the iconRecord for later use (and do a sanity check on it for kicks) - IconRecord* iconRecord = pageRecord->iconRecord(); - - ASSERT(!iconRecord || (iconRecord && m_iconURLToRecordMap.get(iconRecord->iconURL()) == iconRecord)); - - { - MutexLocker locker(m_pendingReadingLock); - - // Since this pageURL is going away, there's no reason anyone would ever be interested in its read results - if (!m_iconURLImportComplete) - m_pageURLsPendingImport.remove(pageURLOriginal); - m_pageURLsInterestedInIcons.remove(pageURLOriginal); - - // If this icon is down to it's last retainer, we don't care about reading it in from disk anymore - if (iconRecord && iconRecord->hasOneRef()) { - m_iconURLToRecordMap.remove(iconRecord->iconURL()); - m_iconsPendingReading.remove(iconRecord); - } - } - - // Mark stuff for deletion from the database only if we're not in private browsing - if (!m_privateBrowsingEnabled) { - MutexLocker locker(m_pendingSyncLock); - m_pageURLsPendingSync.set(pageURLOriginal.copy(), pageRecord->snapshot(true)); - - // If this page is the last page to refer to a particular IconRecord, that IconRecord needs to - // be marked for deletion - if (iconRecord && iconRecord->hasOneRef()) - m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true)); - } - - delete pageRecord; - - if (isOpen()) - scheduleOrDeferSyncTimer(); -} - -void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal, const String& iconURLOriginal) -{ - ASSERT_NOT_SYNC_THREAD(); - - // Cannot do anything with dataOriginal or iconURLOriginal that would end up storing them without deep copying first - - if (!isOpen() || iconURLOriginal.isEmpty()) - return; - - RefPtr<SharedBuffer> data = dataOriginal ? dataOriginal->copy() : 0; - String iconURL = iconURLOriginal.copy(); - - Vector<String> pageURLs; - { - MutexLocker locker(m_urlAndIconLock); - - // If this icon was pending a read, remove it from that set because this new data should override what is on disk - RefPtr<IconRecord> icon = m_iconURLToRecordMap.get(iconURL); - if (icon) { - MutexLocker locker(m_pendingReadingLock); - m_iconsPendingReading.remove(icon.get()); - } else - icon = getOrCreateIconRecord(iconURL); - - // Update the data and set the time stamp - icon->setImageData(data); - icon->setTimestamp((int)currentTime()); - - // Copy the current retaining pageURLs - if any - to notify them of the change - pageURLs.appendRange(icon->retainingPageURLs().begin(), icon->retainingPageURLs().end()); - - // Mark the IconRecord as requiring an update to the database only if private browsing is disabled - if (!m_privateBrowsingEnabled) { - MutexLocker locker(m_pendingSyncLock); - m_iconsPendingSync.set(iconURL, icon->snapshot()); - } - - if (icon->hasOneRef()) { - ASSERT(icon->retainingPageURLs().isEmpty()); - LOG(IconDatabase, "Icon for icon url %s is about to be destroyed - removing mapping for it", urlForLogging(icon->iconURL()).ascii().data()); - m_iconURLToRecordMap.remove(icon->iconURL()); - } - } - - // Send notification out regarding all PageURLs that retain this icon - // But not if we're on the sync thread because that implies this mapping - // comes from the initial import which we don't want notifications for - if (!IS_ICON_SYNC_THREAD()) { - // Start the timer to commit this change - or further delay the timer if it was already started - scheduleOrDeferSyncTimer(); - - // Informal testing shows that draining the autorelease pool every 25 iterations is about as low as we can go - // before performance starts to drop off, but we don't want to increase this number because then accumulated memory usage will go up - AutodrainedPool pool(25); - - for (unsigned i = 0; i < pageURLs.size(); ++i) { - LOG(IconDatabase, "Dispatching notification that retaining pageURL %s has a new icon", urlForLogging(pageURLs[i]).ascii().data()); - m_client->dispatchDidAddIconForPageURL(pageURLs[i]); - - pool.cycle(); - } - } -} - -void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const String& pageURLOriginal) -{ - ASSERT_NOT_SYNC_THREAD(); - - // Cannot do anything with iconURLOriginal or pageURLOriginal that would end up storing them without deep copying first - - ASSERT(!iconURLOriginal.isEmpty()); - - if (!isOpen() || pageURLOriginal.isEmpty()) - return; - - String iconURL, pageURL; - - { - MutexLocker locker(m_urlAndIconLock); - - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal); - - // If the urls already map to each other, bail. - // This happens surprisingly often, and seems to cream iBench performance - if (pageRecord && pageRecord->iconRecord() && pageRecord->iconRecord()->iconURL() == iconURLOriginal) - return; - - pageURL = pageURLOriginal.copy(); - iconURL = iconURLOriginal.copy(); - - if (!pageRecord) { - pageRecord = new PageURLRecord(pageURL); - m_pageURLToRecordMap.set(pageURL, pageRecord); - } - - RefPtr<IconRecord> iconRecord = pageRecord->iconRecord(); - - // Otherwise, set the new icon record for this page - pageRecord->setIconRecord(getOrCreateIconRecord(iconURL)); - - // If the current icon has only a single ref left, it is about to get wiped out. - // Remove it from the in-memory records and don't bother reading it in from disk anymore - if (iconRecord && iconRecord->hasOneRef()) { - ASSERT(iconRecord->retainingPageURLs().size() == 0); - LOG(IconDatabase, "Icon for icon url %s is about to be destroyed - removing mapping for it", urlForLogging(iconRecord->iconURL()).ascii().data()); - m_iconURLToRecordMap.remove(iconRecord->iconURL()); - MutexLocker locker(m_pendingReadingLock); - m_iconsPendingReading.remove(iconRecord.get()); - } - - // And mark this mapping to be added to the database - if (!m_privateBrowsingEnabled) { - MutexLocker locker(m_pendingSyncLock); - m_pageURLsPendingSync.set(pageURL, pageRecord->snapshot()); - - // If the icon is on its last ref, mark it for deletion - if (iconRecord && iconRecord->hasOneRef()) - m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true)); - } - } - - // Since this mapping is new, send the notification out - but not if we're on the sync thread because that implies this mapping - // comes from the initial import which we don't want notifications for - if (!IS_ICON_SYNC_THREAD()) { - // Start the timer to commit this change - or further delay the timer if it was already started - scheduleOrDeferSyncTimer(); - - LOG(IconDatabase, "Dispatching notification that we changed an icon mapping for url %s", urlForLogging(pageURL).ascii().data()); - AutodrainedPool pool; - m_client->dispatchDidAddIconForPageURL(pageURL); - } -} - -IconLoadDecision IconDatabase::loadDecisionForIconURL(const String& iconURL, DocumentLoader* notificationDocumentLoader) -{ - ASSERT_NOT_SYNC_THREAD(); - - if (!isOpen() || iconURL.isEmpty()) - return IconLoadNo; - - // If we have a IconRecord, it should also have its timeStamp marked because there is only two times when we create the IconRecord: - // 1 - When we read the icon urls from disk, getting the timeStamp at the same time - // 2 - When we get a new icon from the loader, in which case the timestamp is set at that time - { - MutexLocker locker(m_urlAndIconLock); - if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) { - LOG(IconDatabase, "Found expiration time on a present icon based on existing IconRecord"); - return (int)currentTime() - icon->getTimestamp() > iconExpirationTime ? IconLoadYes : IconLoadNo; - } - } - - // If we don't have a record for it, but we *have* imported all iconURLs from disk, then we should load it now - MutexLocker readingLocker(m_pendingReadingLock); - if (m_iconURLImportComplete) - return IconLoadYes; - - // Otherwise - since we refuse to perform I/O on the main thread to find out for sure - we return the answer that says - // "You might be asked to load this later, so flag that" - LOG(IconDatabase, "Don't know if we should load %s or not - adding %p to the set of document loaders waiting on a decision", iconURL.ascii().data(), notificationDocumentLoader); - m_loadersPendingDecision.add(notificationDocumentLoader); - - return IconLoadUnknown; -} - -bool IconDatabase::iconDataKnownForIconURL(const String& iconURL) -{ - ASSERT_NOT_SYNC_THREAD(); - - MutexLocker locker(m_urlAndIconLock); - if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) - return icon->imageDataStatus() != ImageDataStatusUnknown; - - return false; -} - -void IconDatabase::setEnabled(bool enabled) -{ - ASSERT_NOT_SYNC_THREAD(); - - if (!enabled && isOpen()) - close(); - m_isEnabled = enabled; -} - -bool IconDatabase::isEnabled() const -{ - ASSERT_NOT_SYNC_THREAD(); - - return m_isEnabled; -} - -void IconDatabase::setPrivateBrowsingEnabled(bool flag) -{ - m_privateBrowsingEnabled = flag; -} - -bool IconDatabase::isPrivateBrowsingEnabled() const -{ - return m_privateBrowsingEnabled; -} - -void IconDatabase::delayDatabaseCleanup() -{ - ++databaseCleanupCounter; - if (databaseCleanupCounter == 1) - LOG(IconDatabase, "Database cleanup is now DISABLED"); -} - -void IconDatabase::allowDatabaseCleanup() -{ - if (--databaseCleanupCounter < 0) - databaseCleanupCounter = 0; - if (databaseCleanupCounter == 0) - LOG(IconDatabase, "Database cleanup is now ENABLED"); -} - -void IconDatabase::checkIntegrityBeforeOpening() -{ - checkIntegrityOnOpen = true; -} - -size_t IconDatabase::pageURLMappingCount() -{ - MutexLocker locker(m_urlAndIconLock); - return m_pageURLToRecordMap.size(); -} - -size_t IconDatabase::retainedPageURLCount() -{ - MutexLocker locker(m_urlAndIconLock); - return m_retainedPageURLs.size(); -} - -size_t IconDatabase::iconRecordCount() -{ - MutexLocker locker(m_urlAndIconLock); - return m_iconURLToRecordMap.size(); -} - -size_t IconDatabase::iconRecordCountWithData() -{ - MutexLocker locker(m_urlAndIconLock); - size_t result = 0; - - HashMap<String, IconRecord*>::iterator i = m_iconURLToRecordMap.begin(); - HashMap<String, IconRecord*>::iterator end = m_iconURLToRecordMap.end(); - - for (; i != end; ++i) - result += ((*i).second->imageDataStatus() == ImageDataStatusPresent); - - return result; -} - -IconDatabase::IconDatabase() - : m_syncThreadRunning(false) - , m_defaultIconRecord(0) - , m_isEnabled(false) - , m_privateBrowsingEnabled(false) - , m_threadTerminationRequested(false) - , m_removeIconsRequested(false) - , m_iconURLImportComplete(false) - , m_initialPruningComplete(false) - , m_client(defaultClient()) - , m_imported(false) - , m_isImportedSet(false) -{ -#if PLATFORM(DARWIN) - ASSERT(pthread_main_np()); -#endif -} - -IconDatabase::~IconDatabase() -{ - ASSERT_NOT_REACHED(); -} - -void IconDatabase::notifyPendingLoadDecisionsOnMainThread(void* context) -{ - static_cast<IconDatabase*>(context)->notifyPendingLoadDecisions(); -} - -void IconDatabase::notifyPendingLoadDecisions() -{ - ASSERT_NOT_SYNC_THREAD(); - - // This method should only be called upon completion of the initial url import from the database - ASSERT(m_iconURLImportComplete); - LOG(IconDatabase, "Notifying all DocumentLoaders that were waiting on a load decision for thier icons"); - - HashSet<RefPtr<DocumentLoader> >::iterator i = m_loadersPendingDecision.begin(); - HashSet<RefPtr<DocumentLoader> >::iterator end = m_loadersPendingDecision.end(); - - for (; i != end; ++i) - if ((*i)->refCount() > 1) - (*i)->iconLoadDecisionAvailable(); - - m_loadersPendingDecision.clear(); -} - -void IconDatabase::wakeSyncThread() -{ - MutexLocker locker(m_syncLock); - m_syncCondition.signal(); -} - -void IconDatabase::scheduleOrDeferSyncTimer() -{ - ASSERT_NOT_SYNC_THREAD(); - if (!m_syncTimer) - m_syncTimer.set(new Timer<IconDatabase>(this, &IconDatabase::syncTimerFired)); - - m_syncTimer->startOneShot(updateTimerDelay); -} - -void IconDatabase::syncTimerFired(Timer<IconDatabase>*) -{ - ASSERT_NOT_SYNC_THREAD(); - wakeSyncThread(); -} - -// ****************** -// *** Any Thread *** -// ****************** - -bool IconDatabase::isOpen() const -{ - MutexLocker locker(m_syncLock); - return m_syncDB.isOpen(); -} - -String IconDatabase::databasePath() const -{ - MutexLocker locker(m_syncLock); - return m_completeDatabasePath.copy(); -} - -String IconDatabase::defaultDatabaseFilename() -{ - static String defaultDatabaseFilename = "WebpageIcons.db"; - return defaultDatabaseFilename.copy(); -} - -// Unlike getOrCreatePageURLRecord(), getOrCreateIconRecord() does not mark the icon as "interested in import" -PassRefPtr<IconRecord> IconDatabase::getOrCreateIconRecord(const String& iconURL) -{ - // Clients of getOrCreateIconRecord() are required to acquire the m_urlAndIconLock before calling this method - ASSERT(!m_urlAndIconLock.tryLock()); - - if (IconRecord* icon = m_iconURLToRecordMap.get(iconURL)) - return icon; - - RefPtr<IconRecord> newIcon = IconRecord::create(iconURL); - m_iconURLToRecordMap.set(iconURL, newIcon.get()); - - return newIcon.release(); -} - -// This method retrieves the existing PageURLRecord, or creates a new one and marks it as "interested in the import" for later notification -PageURLRecord* IconDatabase::getOrCreatePageURLRecord(const String& pageURL) -{ - // Clients of getOrCreatePageURLRecord() are required to acquire the m_urlAndIconLock before calling this method - ASSERT(!m_urlAndIconLock.tryLock()); - - if (pageURL.isEmpty()) - return 0; - - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURL); - - MutexLocker locker(m_pendingReadingLock); - if (!m_iconURLImportComplete) { - // If the initial import of all URLs hasn't completed and we have no page record, we assume we *might* know about this later and create a record for it - if (!pageRecord) { - LOG(IconDatabase, "Creating new PageURLRecord for pageURL %s", urlForLogging(pageURL).ascii().data()); - pageRecord = new PageURLRecord(pageURL); - m_pageURLToRecordMap.set(pageURL, pageRecord); - } - - // If the pageRecord for this page does not have an iconRecord attached to it, then it is a new pageRecord still awaiting the initial import - // Mark the URL as "interested in the result of the import" then bail - if (!pageRecord->iconRecord()) { - m_pageURLsPendingImport.add(pageURL); - return 0; - } - } - - // We've done the initial import of all URLs known in the database. If this record doesn't exist now, it never will - return pageRecord; -} - - -// ************************ -// *** Sync Thread Only *** -// ************************ - -void IconDatabase::importIconURLForPageURL(const String& iconURL, const String& pageURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - // This function is only for setting actual existing url mappings so assert that neither of these URLs are empty - ASSERT(!iconURL.isEmpty() && !pageURL.isEmpty()); - - setIconURLForPageURLInSQLDatabase(iconURL, pageURL); -} - -void IconDatabase::importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - ASSERT(!iconURL.isEmpty()); - - writeIconSnapshotToSQLDatabase(IconSnapshot(iconURL, (int)currentTime(), data.get())); -} - -bool IconDatabase::shouldStopThreadActivity() const -{ - ASSERT_ICON_SYNC_THREAD(); - - return m_threadTerminationRequested || m_removeIconsRequested; -} - -void* IconDatabase::iconDatabaseSyncThreadStart(void* vIconDatabase) -{ - IconDatabase* iconDB = static_cast<IconDatabase*>(vIconDatabase); - - return iconDB->iconDatabaseSyncThread(); -} - -void* IconDatabase::iconDatabaseSyncThread() -{ - // The call to create this thread might not complete before the thread actually starts, so we might fail this ASSERT_ICON_SYNC_THREAD() because the pointer - // to our thread structure hasn't been filled in yet. - // To fix this, the main thread acquires this lock before creating us, then releases the lock after creation is complete. A quick lock/unlock cycle here will - // prevent us from running before that call completes - m_syncLock.lock(); - m_syncLock.unlock(); - - ASSERT_ICON_SYNC_THREAD(); - - LOG(IconDatabase, "(THREAD) IconDatabase sync thread started"); - -#ifndef NDEBUG - double startTime = currentTime(); -#endif - - // Need to create the database path if it doesn't already exist - makeAllDirectories(m_databaseDirectory); - - // Existence of a journal file is evidence of a previous crash/force quit and automatically qualifies - // us to do an integrity check - String journalFilename = m_completeDatabasePath + "-journal"; - if (!checkIntegrityOnOpen) { - AutodrainedPool pool; - checkIntegrityOnOpen = fileExists(journalFilename); - } - - { - MutexLocker locker(m_syncLock); - if (!m_syncDB.open(m_completeDatabasePath)) { - LOG_ERROR("Unable to open icon database at path %s - %s", m_completeDatabasePath.ascii().data(), m_syncDB.lastErrorMsg()); - return 0; - } - } - - if (shouldStopThreadActivity()) - return syncThreadMainLoop(); - -#ifndef NDEBUG - double timeStamp = currentTime(); - LOG(IconDatabase, "(THREAD) Open took %.4f seconds", timeStamp - startTime); -#endif - - performOpenInitialization(); - if (shouldStopThreadActivity()) - return syncThreadMainLoop(); - -#ifndef NDEBUG - double newStamp = currentTime(); - LOG(IconDatabase, "(THREAD) performOpenInitialization() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); - timeStamp = newStamp; -#endif - - if (!imported()) { - LOG(IconDatabase, "(THREAD) Performing Safari2 import procedure"); - SQLiteTransaction importTransaction(m_syncDB); - importTransaction.begin(); - - // Commit the transaction only if the import completes (the import should be atomic) - if (m_client->performImport()) { - setImported(true); - importTransaction.commit(); - } else { - LOG(IconDatabase, "(THREAD) Safari 2 import was cancelled"); - importTransaction.rollback(); - } - - if (shouldStopThreadActivity()) - return syncThreadMainLoop(); - -#ifndef NDEBUG - newStamp = currentTime(); - LOG(IconDatabase, "(THREAD) performImport() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); - timeStamp = newStamp; -#endif - } - - // Uncomment the following line to simulate a long lasting URL import (*HUGE* icon databases, or network home directories) - // while (currentTime() - timeStamp < 10); - - // Read in URL mappings from the database - LOG(IconDatabase, "(THREAD) Starting iconURL import"); - performURLImport(); - - if (shouldStopThreadActivity()) - return syncThreadMainLoop(); - -#ifndef NDEBUG - newStamp = currentTime(); - LOG(IconDatabase, "(THREAD) performURLImport() took %.4f seconds. Entering main loop %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime); -#endif - - LOG(IconDatabase, "(THREAD) Beginning sync"); - return syncThreadMainLoop(); -} - -static int databaseVersionNumber(SQLiteDatabase& db) -{ - return SQLiteStatement(db, "SELECT value FROM IconDatabaseInfo WHERE key = 'Version';").getColumnInt(0); -} - -static bool isValidDatabase(SQLiteDatabase& db) -{ - - // These four tables should always exist in a valid db - if (!db.tableExists("IconInfo") || !db.tableExists("IconData") || !db.tableExists("PageURL") || !db.tableExists("IconDatabaseInfo")) - return false; - - if (databaseVersionNumber(db) < currentDatabaseVersion) { - LOG(IconDatabase, "DB version is not found or below expected valid version"); - return false; - } - - return true; -} - -static void createDatabaseTables(SQLiteDatabase& db) -{ - if (!db.executeCommand("CREATE TABLE PageURL (url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,iconID INTEGER NOT NULL ON CONFLICT FAIL);")) { - LOG_ERROR("Could not create PageURL table in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE INDEX PageURLIndex ON PageURL (url);")) { - LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE TABLE IconInfo (iconID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE ON CONFLICT REPLACE, url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL, stamp INTEGER);")) { - LOG_ERROR("Could not create IconInfo table in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE INDEX IconInfoIndex ON IconInfo (url, iconID);")) { - LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE TABLE IconData (iconID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE ON CONFLICT REPLACE, data BLOB);")) { - LOG_ERROR("Could not create IconData table in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE INDEX IconDataIndex ON IconData (iconID);")) { - LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand("CREATE TABLE IconDatabaseInfo (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) { - LOG_ERROR("Could not create IconDatabaseInfo table in database (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } - if (!db.executeCommand(String("INSERT INTO IconDatabaseInfo VALUES ('Version', ") + String::number(currentDatabaseVersion) + ");")) { - LOG_ERROR("Could not insert icon database version into IconDatabaseInfo table (%i) - %s", db.lastError(), db.lastErrorMsg()); - db.close(); - return; - } -} - -void IconDatabase::performOpenInitialization() -{ - ASSERT_ICON_SYNC_THREAD(); - - if (!isOpen()) - return; - - if (checkIntegrityOnOpen) { - checkIntegrityOnOpen = false; - if (!checkIntegrity()) { - LOG(IconDatabase, "Integrity check was bad - dumping IconDatabase"); - - m_syncDB.close(); - - { - MutexLocker locker(m_syncLock); - // Should've been consumed by SQLite, delete just to make sure we don't see it again in the future; - deleteFile(m_completeDatabasePath + "-journal"); - deleteFile(m_completeDatabasePath); - } - - // Reopen the write database, creating it from scratch - if (!m_syncDB.open(m_completeDatabasePath)) { - LOG_ERROR("Unable to open icon database at path %s - %s", m_completeDatabasePath.ascii().data(), m_syncDB.lastErrorMsg()); - return; - } - } - } - - int version = databaseVersionNumber(m_syncDB); - - if (version > currentDatabaseVersion) { - LOG(IconDatabase, "Database version number %i is greater than our current version number %i - closing the database to prevent overwriting newer versions", version, currentDatabaseVersion); - m_syncDB.close(); - m_threadTerminationRequested = true; - return; - } - - if (!isValidDatabase(m_syncDB)) { - LOG(IconDatabase, "%s is missing or in an invalid state - reconstructing", m_completeDatabasePath.ascii().data()); - m_syncDB.clearAllTables(); - createDatabaseTables(m_syncDB); - } - - // Reduce sqlite RAM cache size from default 2000 pages (~1.5kB per page). 3MB of cache for icon database is overkill - if (!SQLiteStatement(m_syncDB, "PRAGMA cache_size = 200;").executeCommand()) - LOG_ERROR("SQLite database could not set cache_size"); -} - -bool IconDatabase::checkIntegrity() -{ - ASSERT_ICON_SYNC_THREAD(); - - SQLiteStatement integrity(m_syncDB, "PRAGMA integrity_check;"); - if (integrity.prepare() != SQLResultOk) { - LOG_ERROR("checkIntegrity failed to execute"); - return false; - } - - int resultCode = integrity.step(); - if (resultCode == SQLResultOk) - return true; - - if (resultCode != SQLResultRow) - return false; - - int columns = integrity.columnCount(); - if (columns != 1) { - LOG_ERROR("Received %i columns performing integrity check, should be 1", columns); - return false; - } - - String resultText = integrity.getColumnText(0); - - // A successful, no-error integrity check will be "ok" - all other strings imply failure - if (resultText == "ok") - return true; - - LOG_ERROR("Icon database integrity check failed - \n%s", resultText.ascii().data()); - return false; -} - -void IconDatabase::performURLImport() -{ - ASSERT_ICON_SYNC_THREAD(); - - SQLiteStatement query(m_syncDB, "SELECT PageURL.url, IconInfo.url, IconInfo.stamp FROM PageURL INNER JOIN IconInfo ON PageURL.iconID=IconInfo.iconID;"); - - if (query.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare icon url import query"); - return; - } - - // Informal testing shows that draining the autorelease pool every 25 iterations is about as low as we can go - // before performance starts to drop off, but we don't want to increase this number because then accumulated memory usage will go up - AutodrainedPool pool(25); - - int result = query.step(); - while (result == SQLResultRow) { - String pageURL = query.getColumnText(0); - String iconURL = query.getColumnText(1); - - { - MutexLocker locker(m_urlAndIconLock); - - PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURL); - - // If the pageRecord doesn't exist in this map, then no one has retained this pageURL - // If the s_databaseCleanupCounter count is non-zero, then we're not supposed to be pruning the database in any manner, - // so go ahead and actually create a pageURLRecord for this url even though it's not retained. - // If database cleanup *is* allowed, we don't want to bother pulling in a page url from disk that noone is actually interested - // in - we'll prune it later instead! - if (!pageRecord && databaseCleanupCounter && !pageURL.isEmpty()) { - pageRecord = new PageURLRecord(pageURL); - m_pageURLToRecordMap.set(pageURL, pageRecord); - } - - if (pageRecord) { - IconRecord* currentIcon = pageRecord->iconRecord(); - - if (!currentIcon || currentIcon->iconURL() != iconURL) { - pageRecord->setIconRecord(getOrCreateIconRecord(iconURL)); - currentIcon = pageRecord->iconRecord(); - } - - // Regardless, the time stamp from disk still takes precedence. Until we read this icon from disk, we didn't think we'd seen it before - // so we marked the timestamp as "now", but it's really much older - currentIcon->setTimestamp(query.getColumnInt(2)); - } - } - - // FIXME: Currently the WebKit API supports 1 type of notification that is sent whenever we get an Icon URL for a Page URL. We might want to re-purpose it to work for - // getting the actually icon itself also (so each pageurl would get this notification twice) or we might want to add a second type of notification - - // one for the URL and one for the Image itself - // Note that WebIconDatabase is not neccessarily API so we might be able to make this change - { - MutexLocker locker(m_pendingReadingLock); - if (m_pageURLsPendingImport.contains(pageURL)) { - m_client->dispatchDidAddIconForPageURL(pageURL); - m_pageURLsPendingImport.remove(pageURL); - - pool.cycle(); - } - } - - // Stop the import at any time of the thread has been asked to shutdown - if (shouldStopThreadActivity()) { - LOG(IconDatabase, "IconDatabase asked to terminate during performURLImport()"); - return; - } - - result = query.step(); - } - - if (result != SQLResultDone) - LOG(IconDatabase, "Error reading page->icon url mappings from database"); - - // Clear the m_pageURLsPendingImport set - either the page URLs ended up with an iconURL (that we'll notify about) or not, - // but after m_iconURLImportComplete is set to true, we don't care about this set anymore - Vector<String> urls; - { - MutexLocker locker(m_pendingReadingLock); - - urls.appendRange(m_pageURLsPendingImport.begin(), m_pageURLsPendingImport.end()); - m_pageURLsPendingImport.clear(); - m_iconURLImportComplete = true; - } - - Vector<String> urlsToNotify; - - // Loop through the urls pending import - // Remove unretained ones if database cleanup is allowed - // Keep a set of ones that are retained and pending notification - - { - MutexLocker locker(m_urlAndIconLock); - - for (unsigned i = 0; i < urls.size(); ++i) { - if (!m_retainedPageURLs.contains(urls[i])) { - PageURLRecord* record = m_pageURLToRecordMap.get(urls[i]); - if (record && !databaseCleanupCounter) { - m_pageURLToRecordMap.remove(urls[i]); - IconRecord* iconRecord = record->iconRecord(); - - // If this page is the only remaining retainer of its icon, mark that icon for deletion and don't bother - // reading anything related to it - if (iconRecord && iconRecord->hasOneRef()) { - m_iconURLToRecordMap.remove(iconRecord->iconURL()); - - { - MutexLocker locker(m_pendingReadingLock); - m_pageURLsInterestedInIcons.remove(urls[i]); - m_iconsPendingReading.remove(iconRecord); - } - { - MutexLocker locker(m_pendingSyncLock); - m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true)); - } - } - - delete record; - } - } else { - urlsToNotify.append(urls[i]); - } - } - } - - LOG(IconDatabase, "Notifying %zu interested page URLs that their icon URL is known due to the import", urlsToNotify.size()); - // Now that we don't hold any locks, perform the actual notifications - for (unsigned i = 0; i < urlsToNotify.size(); ++i) { - LOG(IconDatabase, "Notifying icon info known for pageURL %s", urlsToNotify[i].ascii().data()); - m_client->dispatchDidAddIconForPageURL(urlsToNotify[i]); - if (shouldStopThreadActivity()) - return; - - pool.cycle(); - } - - // Notify all DocumentLoaders that were waiting for an icon load decision on the main thread - callOnMainThread(notifyPendingLoadDecisionsOnMainThread, this); -} - -void* IconDatabase::syncThreadMainLoop() -{ - ASSERT_ICON_SYNC_THREAD(); - static bool prunedUnretainedIcons = false; - - m_syncLock.lock(); - - // It's possible thread termination is requested before the main loop even starts - in that case, just skip straight to cleanup - while (!m_threadTerminationRequested) { - m_syncLock.unlock(); - -#ifndef NDEBUG - double timeStamp = currentTime(); -#endif - LOG(IconDatabase, "(THREAD) Main work loop starting"); - - // If we should remove all icons, do it now. This is an uninteruptible procedure that we will always do before quitting if it is requested - if (m_removeIconsRequested) { - removeAllIconsOnThread(); - m_removeIconsRequested = false; - } - - // Then, if the thread should be quitting, quit now! - if (m_threadTerminationRequested) - break; - - bool didAnyWork = true; - while (didAnyWork) { - bool didWrite = writeToDatabase(); - if (shouldStopThreadActivity()) - break; - - didAnyWork = readFromDatabase(); - if (shouldStopThreadActivity()) - break; - - // Prune unretained icons after the first time we sync anything out to the database - // This way, pruning won't be the only operation we perform to the database by itself - // We also don't want to bother doing this if the thread should be terminating (the user is quitting) - // or if private browsing is enabled - // We also don't want to prune if the m_databaseCleanupCounter count is non-zero - that means someone - // has asked to delay pruning - if (didWrite && !m_privateBrowsingEnabled && !prunedUnretainedIcons && !databaseCleanupCounter) { -#ifndef NDEBUG - double time = currentTime(); -#endif - LOG(IconDatabase, "(THREAD) Starting pruneUnretainedIcons()"); - - pruneUnretainedIcons(); - - LOG(IconDatabase, "(THREAD) pruneUnretainedIcons() took %.4f seconds", currentTime() - time); - - // If pruneUnretainedIcons() returned early due to requested thread termination, its still okay - // to mark prunedUnretainedIcons true because we're about to terminate anyway - prunedUnretainedIcons = true; - } - - didAnyWork = didAnyWork || didWrite; - if (shouldStopThreadActivity()) - break; - } - -#ifndef NDEBUG - double newstamp = currentTime(); - LOG(IconDatabase, "(THREAD) Main work loop ran for %.4f seconds, %s requested to terminate", newstamp - timeStamp, shouldStopThreadActivity() ? "was" : "was not"); -#endif - - m_syncLock.lock(); - - // There is some condition that is asking us to stop what we're doing now and handle a special case - // This is either removing all icons, or shutting down the thread to quit the app - // We handle those at the top of this main loop so continue to jump back up there - if (shouldStopThreadActivity()) - continue; - - m_syncCondition.wait(m_syncLock); - } - m_syncLock.unlock(); - - // Thread is terminating at this point - return cleanupSyncThread(); -} - -bool IconDatabase::readFromDatabase() -{ - ASSERT_ICON_SYNC_THREAD(); - -#ifndef NDEBUG - double timeStamp = currentTime(); -#endif - - bool didAnyWork = false; - - // We'll make a copy of the sets of things that need to be read. Then we'll verify at the time of updating the record that it still wants to be updated - // This way we won't hold the lock for a long period of time - Vector<IconRecord*> icons; - { - MutexLocker locker(m_pendingReadingLock); - icons.appendRange(m_iconsPendingReading.begin(), m_iconsPendingReading.end()); - } - - // Keep track of icons we actually read to notify them of the new icon - HashSet<String> urlsToNotify; - - for (unsigned i = 0; i < icons.size(); ++i) { - didAnyWork = true; - RefPtr<SharedBuffer> imageData = getImageDataForIconURLFromSQLDatabase(icons[i]->iconURL()); - - // Verify this icon still wants to be read from disk - { - MutexLocker urlLocker(m_urlAndIconLock); - { - MutexLocker readLocker(m_pendingReadingLock); - - if (m_iconsPendingReading.contains(icons[i])) { - // Set the new data - icons[i]->setImageData(imageData.get()); - - // Remove this icon from the set that needs to be read - m_iconsPendingReading.remove(icons[i]); - - // We have a set of all Page URLs that retain this icon as well as all PageURLs waiting for an icon - // We want to find the intersection of these two sets to notify them - // Check the sizes of these two sets to minimize the number of iterations - const HashSet<String>* outerHash; - const HashSet<String>* innerHash; - - if (icons[i]->retainingPageURLs().size() > m_pageURLsInterestedInIcons.size()) { - outerHash = &m_pageURLsInterestedInIcons; - innerHash = &(icons[i]->retainingPageURLs()); - } else { - innerHash = &m_pageURLsInterestedInIcons; - outerHash = &(icons[i]->retainingPageURLs()); - } - - HashSet<String>::const_iterator iter = outerHash->begin(); - HashSet<String>::const_iterator end = outerHash->end(); - for (; iter != end; ++iter) { - if (innerHash->contains(*iter)) { - LOG(IconDatabase, "%s is interesting in the icon we just read. Adding it to the list and removing it from the interested set", urlForLogging(*iter).ascii().data()); - urlsToNotify.add(*iter); - } - - // If we ever get to the point were we've seen every url interested in this icon, break early - if (urlsToNotify.size() == m_pageURLsInterestedInIcons.size()) - break; - } - - // We don't need to notify a PageURL twice, so all the ones we're about to notify can be removed from the interested set - if (urlsToNotify.size() == m_pageURLsInterestedInIcons.size()) - m_pageURLsInterestedInIcons.clear(); - else { - iter = urlsToNotify.begin(); - end = urlsToNotify.end(); - for (; iter != end; ++iter) - m_pageURLsInterestedInIcons.remove(*iter); - } - } - } - } - - if (shouldStopThreadActivity()) - return didAnyWork; - - // Informal testing shows that draining the autorelease pool every 25 iterations is about as low as we can go - // before performance starts to drop off, but we don't want to increase this number because then accumulated memory usage will go up - AutodrainedPool pool(25); - - // Now that we don't hold any locks, perform the actual notifications - HashSet<String>::iterator iter = urlsToNotify.begin(); - HashSet<String>::iterator end = urlsToNotify.end(); - for (unsigned iteration = 0; iter != end; ++iter, ++iteration) { - LOG(IconDatabase, "Notifying icon received for pageURL %s", urlForLogging(*iter).ascii().data()); - m_client->dispatchDidAddIconForPageURL(*iter); - if (shouldStopThreadActivity()) - return didAnyWork; - - pool.cycle(); - } - - LOG(IconDatabase, "Done notifying %i pageURLs who just received their icons", urlsToNotify.size()); - urlsToNotify.clear(); - - if (shouldStopThreadActivity()) - return didAnyWork; - } - - LOG(IconDatabase, "Reading from database took %.4f seconds", currentTime() - timeStamp); - - return didAnyWork; -} - -bool IconDatabase::writeToDatabase() -{ - ASSERT_ICON_SYNC_THREAD(); - -#ifndef NDEBUG - double timeStamp = currentTime(); -#endif - - bool didAnyWork = false; - - // We can copy the current work queue then clear it out - If any new work comes in while we're writing out, - // we'll pick it up on the next pass. This greatly simplifies the locking strategy for this method and remains cohesive with changes - // asked for by the database on the main thread - Vector<IconSnapshot> iconSnapshots; - Vector<PageURLSnapshot> pageSnapshots; - { - MutexLocker locker(m_pendingSyncLock); - - iconSnapshots.appendRange(m_iconsPendingSync.begin().values(), m_iconsPendingSync.end().values()); - m_iconsPendingSync.clear(); - - pageSnapshots.appendRange(m_pageURLsPendingSync.begin().values(), m_pageURLsPendingSync.end().values()); - m_pageURLsPendingSync.clear(); - } - - if (iconSnapshots.size() || pageSnapshots.size()) - didAnyWork = true; - - SQLiteTransaction syncTransaction(m_syncDB); - syncTransaction.begin(); - - for (unsigned i = 0; i < iconSnapshots.size(); ++i) { - writeIconSnapshotToSQLDatabase(iconSnapshots[i]); - LOG(IconDatabase, "Wrote IconRecord for IconURL %s with timeStamp of %i to the DB", urlForLogging(iconSnapshots[i].iconURL).ascii().data(), iconSnapshots[i].timestamp); - } - - for (unsigned i = 0; i < pageSnapshots.size(); ++i) { - // If the icon URL is empty, this page is meant to be deleted - // ASSERTs are sanity checks to make sure the mappings exist if they should and don't if they shouldn't - if (pageSnapshots[i].iconURL.isEmpty()) - removePageURLFromSQLDatabase(pageSnapshots[i].pageURL); - else - setIconURLForPageURLInSQLDatabase(pageSnapshots[i].iconURL, pageSnapshots[i].pageURL); - LOG(IconDatabase, "Committed IconURL for PageURL %s to database", urlForLogging(pageSnapshots[i].pageURL).ascii().data()); - } - - syncTransaction.commit(); - - // Check to make sure there are no dangling PageURLs - If there are, we want to output one log message but not spam the console potentially every few seconds - if (didAnyWork) - checkForDanglingPageURLs(false); - - LOG(IconDatabase, "Updating the database took %.4f seconds", currentTime() - timeStamp); - - return didAnyWork; -} - -void IconDatabase::pruneUnretainedIcons() -{ - ASSERT_ICON_SYNC_THREAD(); - - if (!isOpen()) - return; - - // This method should only be called once per run - ASSERT(!m_initialPruningComplete); - - // This method relies on having read in all page URLs from the database earlier. - ASSERT(m_iconURLImportComplete); - - // Get the known PageURLs from the db, and record the ID of any that are not in the retain count set. - Vector<int64_t> pageIDsToDelete; - - SQLiteStatement pageSQL(m_syncDB, "SELECT rowid, url FROM PageURL;"); - pageSQL.prepare(); - - int result; - while ((result = pageSQL.step()) == SQLResultRow) { - MutexLocker locker(m_urlAndIconLock); - if (!m_pageURLToRecordMap.contains(pageSQL.getColumnText(1))) - pageIDsToDelete.append(pageSQL.getColumnInt64(0)); - } - - if (result != SQLResultDone) - LOG_ERROR("Error reading PageURL table from on-disk DB"); - pageSQL.finalize(); - - // Delete page URLs that were in the table, but not in our retain count set. - size_t numToDelete = pageIDsToDelete.size(); - if (numToDelete) { - SQLiteTransaction pruningTransaction(m_syncDB); - pruningTransaction.begin(); - - SQLiteStatement pageDeleteSQL(m_syncDB, "DELETE FROM PageURL WHERE rowid = (?);"); - pageDeleteSQL.prepare(); - for (size_t i = 0; i < numToDelete; ++i) { - LOG(IconDatabase, "Pruning page with rowid %lli from disk", pageIDsToDelete[i]); - pageDeleteSQL.bindInt64(1, pageIDsToDelete[i]); - int result = pageDeleteSQL.step(); - if (result != SQLResultDone) - LOG_ERROR("Unabled to delete page with id %lli from disk", pageIDsToDelete[i]); - pageDeleteSQL.reset(); - - // If the thread was asked to terminate, we should commit what pruning we've done so far, figuring we can - // finish the rest later (hopefully) - if (shouldStopThreadActivity()) { - pruningTransaction.commit(); - return; - } - } - pruningTransaction.commit(); - pageDeleteSQL.finalize(); - } - - // Deleting unreferenced icons from the Icon tables has to be atomic - - // If the user quits while these are taking place, they might have to wait. Thankfully this will rarely be an issue - // A user on a network home directory with a wildly inconsistent database might see quite a pause... - - SQLiteTransaction pruningTransaction(m_syncDB); - pruningTransaction.begin(); - - // Wipe Icons that aren't retained - if (!m_syncDB.executeCommand("DELETE FROM IconData WHERE iconID NOT IN (SELECT iconID FROM PageURL);")) - LOG_ERROR("Failed to execute SQL to prune unretained icons from the on-disk IconData table"); - if (!m_syncDB.executeCommand("DELETE FROM IconInfo WHERE iconID NOT IN (SELECT iconID FROM PageURL);")) - LOG_ERROR("Failed to execute SQL to prune unretained icons from the on-disk IconInfo table"); - - pruningTransaction.commit(); - - checkForDanglingPageURLs(true); - - m_initialPruningComplete = true; -} - -void IconDatabase::checkForDanglingPageURLs(bool pruneIfFound) -{ - ASSERT_ICON_SYNC_THREAD(); - - // This check can be relatively expensive so we don't do it in a release build unless the caller has asked us to prune any dangling - // entries. We also don't want to keep performing this check and reporting this error if it has already found danglers before so we - // keep track of whether we've found any. We skip the check in the release build pretending to have already found danglers already. -#ifndef NDEBUG - static bool danglersFound = true; -#else - static bool danglersFound = false; -#endif - - if ((pruneIfFound || !danglersFound) && SQLiteStatement(m_syncDB, "SELECT url FROM PageURL WHERE PageURL.iconID NOT IN (SELECT iconID FROM IconInfo) LIMIT 1;").returnsAtLeastOneResult()) { - danglersFound = true; - LOG(IconDatabase, "Dangling PageURL entries found"); - if (pruneIfFound && !m_syncDB.executeCommand("DELETE FROM PageURL WHERE iconID NOT IN (SELECT iconID FROM IconInfo);")) - LOG(IconDatabase, "Unable to prune dangling PageURLs"); - } -} - -void IconDatabase::removeAllIconsOnThread() -{ - ASSERT_ICON_SYNC_THREAD(); - - LOG(IconDatabase, "Removing all icons on the sync thread"); - - // Delete all the prepared statements so they can start over - deleteAllPreparedStatements(); - - // To reset the on-disk database, we'll wipe all its tables then vacuum it - // This is easier and safer than closing it, deleting the file, and recreating from scratch - m_syncDB.clearAllTables(); - m_syncDB.runVacuumCommand(); - createDatabaseTables(m_syncDB); - - LOG(IconDatabase, "Dispatching notification that we removed all icons"); - m_client->dispatchDidRemoveAllIcons(); -} - -void IconDatabase::deleteAllPreparedStatements() -{ - ASSERT_ICON_SYNC_THREAD(); - - m_setIconIDForPageURLStatement.set(0); - m_removePageURLStatement.set(0); - m_getIconIDForIconURLStatement.set(0); - m_getImageDataForIconURLStatement.set(0); - m_addIconToIconInfoStatement.set(0); - m_addIconToIconDataStatement.set(0); - m_getImageDataStatement.set(0); - m_deletePageURLsForIconURLStatement.set(0); - m_deleteIconFromIconInfoStatement.set(0); - m_deleteIconFromIconDataStatement.set(0); - m_updateIconInfoStatement.set(0); - m_updateIconDataStatement.set(0); - m_setIconInfoStatement.set(0); - m_setIconDataStatement.set(0); -} - -void* IconDatabase::cleanupSyncThread() -{ - ASSERT_ICON_SYNC_THREAD(); - -#ifndef NDEBUG - double timeStamp = currentTime(); -#endif - - // If the removeIcons flag is set, remove all icons from the db. - if (m_removeIconsRequested) - removeAllIconsOnThread(); - - // Sync remaining icons out - LOG(IconDatabase, "(THREAD) Doing final writeout and closure of sync thread"); - writeToDatabase(); - - // Close the database - MutexLocker locker(m_syncLock); - - m_databaseDirectory = String(); - m_completeDatabasePath = String(); - deleteAllPreparedStatements(); - m_syncDB.close(); - -#ifndef NDEBUG - LOG(IconDatabase, "(THREAD) Final closure took %.4f seconds", currentTime() - timeStamp); -#endif - - m_syncThreadRunning = false; - return 0; -} - -bool IconDatabase::imported() -{ - ASSERT_ICON_SYNC_THREAD(); - - if (m_isImportedSet) - return m_imported; - - SQLiteStatement query(m_syncDB, "SELECT IconDatabaseInfo.value FROM IconDatabaseInfo WHERE IconDatabaseInfo.key = \"ImportedSafari2Icons\";"); - if (query.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare imported statement"); - return false; - } - - int result = query.step(); - if (result == SQLResultRow) - result = query.getColumnInt(0); - else { - if (result != SQLResultDone) - LOG_ERROR("imported statement failed"); - result = 0; - } - - m_isImportedSet = true; - return m_imported = result; -} - -void IconDatabase::setImported(bool import) -{ - ASSERT_ICON_SYNC_THREAD(); - - m_imported = import; - m_isImportedSet = true; - - String queryString = import ? - "INSERT INTO IconDatabaseInfo (key, value) VALUES (\"ImportedSafari2Icons\", 1);" : - "INSERT INTO IconDatabaseInfo (key, value) VALUES (\"ImportedSafari2Icons\", 0);"; - - SQLiteStatement query(m_syncDB, queryString); - - if (query.prepare() != SQLResultOk) { - LOG_ERROR("Unable to prepare set imported statement"); - return; - } - - if (query.step() != SQLResultDone) - LOG_ERROR("set imported statement failed"); -} - -// readySQLiteStatement() handles two things -// 1 - If the SQLDatabase& argument is different, the statement must be destroyed and remade. This happens when the user -// switches to and from private browsing -// 2 - Lazy construction of the Statement in the first place, in case we've never made this query before -inline void readySQLiteStatement(OwnPtr<SQLiteStatement>& statement, SQLiteDatabase& db, const String& str) -{ - if (statement && (statement->database() != &db || statement->isExpired())) { - if (statement->isExpired()) - LOG(IconDatabase, "SQLiteStatement associated with %s is expired", str.ascii().data()); - statement.set(0); - } - if (!statement) { - statement.set(new SQLiteStatement(db, str)); - if (statement->prepare() != SQLResultOk) - LOG_ERROR("Preparing statement %s failed", str.ascii().data()); - } -} - -void IconDatabase::setIconURLForPageURLInSQLDatabase(const String& iconURL, const String& pageURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - int64_t iconID = getIconIDForIconURLFromSQLDatabase(iconURL); - - if (!iconID) - iconID = addIconURLToSQLDatabase(iconURL); - - if (!iconID) { - LOG_ERROR("Failed to establish an ID for iconURL %s", urlForLogging(iconURL).ascii().data()); - ASSERT(false); - return; - } - - setIconIDForPageURLInSQLDatabase(iconID, pageURL); -} - -void IconDatabase::setIconIDForPageURLInSQLDatabase(int64_t iconID, const String& pageURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - readySQLiteStatement(m_setIconIDForPageURLStatement, m_syncDB, "INSERT INTO PageURL (url, iconID) VALUES ((?), ?);"); - m_setIconIDForPageURLStatement->bindText(1, pageURL); - m_setIconIDForPageURLStatement->bindInt64(2, iconID); - - int result = m_setIconIDForPageURLStatement->step(); - if (result != SQLResultDone) { - ASSERT(false); - LOG_ERROR("setIconIDForPageURLQuery failed for url %s", urlForLogging(pageURL).ascii().data()); - } - - m_setIconIDForPageURLStatement->reset(); -} - -void IconDatabase::removePageURLFromSQLDatabase(const String& pageURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - readySQLiteStatement(m_removePageURLStatement, m_syncDB, "DELETE FROM PageURL WHERE url = (?);"); - m_removePageURLStatement->bindText(1, pageURL); - - if (m_removePageURLStatement->step() != SQLResultDone) - LOG_ERROR("removePageURLFromSQLDatabase failed for url %s", urlForLogging(pageURL).ascii().data()); - - m_removePageURLStatement->reset(); -} - - -int64_t IconDatabase::getIconIDForIconURLFromSQLDatabase(const String& iconURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - readySQLiteStatement(m_getIconIDForIconURLStatement, m_syncDB, "SELECT IconInfo.iconID FROM IconInfo WHERE IconInfo.url = (?);"); - m_getIconIDForIconURLStatement->bindText(1, iconURL); - - int64_t result = m_getIconIDForIconURLStatement->step(); - if (result == SQLResultRow) - result = m_getIconIDForIconURLStatement->getColumnInt64(0); - else { - if (result != SQLResultDone) - LOG_ERROR("getIconIDForIconURLFromSQLDatabase failed for url %s", urlForLogging(iconURL).ascii().data()); - result = 0; - } - - m_getIconIDForIconURLStatement->reset(); - return result; -} - -int64_t IconDatabase::addIconURLToSQLDatabase(const String& iconURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - // There would be a transaction here to make sure these two inserts are atomic - // In practice the only caller of this method is always wrapped in a transaction itself so placing another - // here is unnecessary - - readySQLiteStatement(m_addIconToIconInfoStatement, m_syncDB, "INSERT INTO IconInfo (url, stamp) VALUES (?, 0);"); - m_addIconToIconInfoStatement->bindText(1, iconURL); - - int result = m_addIconToIconInfoStatement->step(); - m_addIconToIconInfoStatement->reset(); - if (result != SQLResultDone) { - LOG_ERROR("addIconURLToSQLDatabase failed to insert %s into IconInfo", urlForLogging(iconURL).ascii().data()); - return 0; - } - int64_t iconID = m_syncDB.lastInsertRowID(); - - readySQLiteStatement(m_addIconToIconDataStatement, m_syncDB, "INSERT INTO IconData (iconID, data) VALUES (?, ?);"); - m_addIconToIconDataStatement->bindInt64(1, iconID); - - result = m_addIconToIconDataStatement->step(); - m_addIconToIconDataStatement->reset(); - if (result != SQLResultDone) { - LOG_ERROR("addIconURLToSQLDatabase failed to insert %s into IconData", urlForLogging(iconURL).ascii().data()); - return 0; - } - - return iconID; -} - -PassRefPtr<SharedBuffer> IconDatabase::getImageDataForIconURLFromSQLDatabase(const String& iconURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - RefPtr<SharedBuffer> imageData; - - readySQLiteStatement(m_getImageDataForIconURLStatement, m_syncDB, "SELECT IconData.data FROM IconData WHERE IconData.iconID IN (SELECT iconID FROM IconInfo WHERE IconInfo.url = (?));"); - m_getImageDataForIconURLStatement->bindText(1, iconURL); - - int result = m_getImageDataForIconURLStatement->step(); - if (result == SQLResultRow) { - Vector<char> data; - m_getImageDataForIconURLStatement->getColumnBlobAsVector(0, data); - imageData = SharedBuffer::create(data.data(), data.size()); - } else if (result != SQLResultDone) - LOG_ERROR("getImageDataForIconURLFromSQLDatabase failed for url %s", urlForLogging(iconURL).ascii().data()); - - m_getImageDataForIconURLStatement->reset(); - - return imageData.release(); -} - -void IconDatabase::removeIconFromSQLDatabase(const String& iconURL) -{ - ASSERT_ICON_SYNC_THREAD(); - - if (iconURL.isEmpty()) - return; - - // There would be a transaction here to make sure these removals are atomic - // In practice the only caller of this method is always wrapped in a transaction itself so placing another here is unnecessary - - // It's possible this icon is not in the database because of certain rapid browsing patterns (such as a stress test) where the - // icon is marked to be added then marked for removal before it is ever written to disk. No big deal, early return - int64_t iconID = getIconIDForIconURLFromSQLDatabase(iconURL); - if (!iconID) - return; - - readySQLiteStatement(m_deletePageURLsForIconURLStatement, m_syncDB, "DELETE FROM PageURL WHERE PageURL.iconID = (?);"); - m_deletePageURLsForIconURLStatement->bindInt64(1, iconID); - - if (m_deletePageURLsForIconURLStatement->step() != SQLResultDone) - LOG_ERROR("m_deletePageURLsForIconURLStatement failed for url %s", urlForLogging(iconURL).ascii().data()); - - readySQLiteStatement(m_deleteIconFromIconInfoStatement, m_syncDB, "DELETE FROM IconInfo WHERE IconInfo.iconID = (?);"); - m_deleteIconFromIconInfoStatement->bindInt64(1, iconID); - - if (m_deleteIconFromIconInfoStatement->step() != SQLResultDone) - LOG_ERROR("m_deleteIconFromIconInfoStatement failed for url %s", urlForLogging(iconURL).ascii().data()); - - readySQLiteStatement(m_deleteIconFromIconDataStatement, m_syncDB, "DELETE FROM IconData WHERE IconData.iconID = (?);"); - m_deleteIconFromIconDataStatement->bindInt64(1, iconID); - - if (m_deleteIconFromIconDataStatement->step() != SQLResultDone) - LOG_ERROR("m_deleteIconFromIconDataStatement failed for url %s", urlForLogging(iconURL).ascii().data()); - - m_deletePageURLsForIconURLStatement->reset(); - m_deleteIconFromIconInfoStatement->reset(); - m_deleteIconFromIconDataStatement->reset(); -} - -void IconDatabase::writeIconSnapshotToSQLDatabase(const IconSnapshot& snapshot) -{ - ASSERT_ICON_SYNC_THREAD(); - - if (snapshot.iconURL.isEmpty()) - return; - - // A nulled out timestamp and data means this icon is destined to be deleted - do that instead of writing it out - if (!snapshot.timestamp && !snapshot.data) { - LOG(IconDatabase, "Removing %s from on-disk database", urlForLogging(snapshot.iconURL).ascii().data()); - removeIconFromSQLDatabase(snapshot.iconURL); - return; - } - - // There would be a transaction here to make sure these removals are atomic - // In practice the only caller of this method is always wrapped in a transaction itself so placing another here is unnecessary - - // Get the iconID for this url - int64_t iconID = getIconIDForIconURLFromSQLDatabase(snapshot.iconURL); - - // If there is already an iconID in place, update the database. - // Otherwise, insert new records - if (iconID) { - readySQLiteStatement(m_updateIconInfoStatement, m_syncDB, "UPDATE IconInfo SET stamp = ?, url = ? WHERE iconID = ?;"); - m_updateIconInfoStatement->bindInt64(1, snapshot.timestamp); - m_updateIconInfoStatement->bindText(2, snapshot.iconURL); - m_updateIconInfoStatement->bindInt64(3, iconID); - - if (m_updateIconInfoStatement->step() != SQLResultDone) - LOG_ERROR("Failed to update icon info for url %s", urlForLogging(snapshot.iconURL).ascii().data()); - - m_updateIconInfoStatement->reset(); - - readySQLiteStatement(m_updateIconDataStatement, m_syncDB, "UPDATE IconData SET data = ? WHERE iconID = ?;"); - m_updateIconDataStatement->bindInt64(2, iconID); - - // If we *have* image data, bind it to this statement - Otherwise bind "null" for the blob data, - // signifying that this icon doesn't have any data - if (snapshot.data && snapshot.data->size()) - m_updateIconDataStatement->bindBlob(1, snapshot.data->data(), snapshot.data->size()); - else - m_updateIconDataStatement->bindNull(1); - - if (m_updateIconDataStatement->step() != SQLResultDone) - LOG_ERROR("Failed to update icon data for url %s", urlForLogging(snapshot.iconURL).ascii().data()); - - m_updateIconDataStatement->reset(); - } else { - readySQLiteStatement(m_setIconInfoStatement, m_syncDB, "INSERT INTO IconInfo (url,stamp) VALUES (?, ?);"); - m_setIconInfoStatement->bindText(1, snapshot.iconURL); - m_setIconInfoStatement->bindInt64(2, snapshot.timestamp); - - if (m_setIconInfoStatement->step() != SQLResultDone) - LOG_ERROR("Failed to set icon info for url %s", urlForLogging(snapshot.iconURL).ascii().data()); - - m_setIconInfoStatement->reset(); - - int64_t iconID = m_syncDB.lastInsertRowID(); - - readySQLiteStatement(m_setIconDataStatement, m_syncDB, "INSERT INTO IconData (iconID, data) VALUES (?, ?);"); - m_setIconDataStatement->bindInt64(1, iconID); - - // If we *have* image data, bind it to this statement - Otherwise bind "null" for the blob data, - // signifying that this icon doesn't have any data - if (snapshot.data && snapshot.data->size()) - m_setIconDataStatement->bindBlob(2, snapshot.data->data(), snapshot.data->size()); - else - m_setIconDataStatement->bindNull(2); - - if (m_setIconDataStatement->step() != SQLResultDone) - LOG_ERROR("Failed to set icon data for url %s", urlForLogging(snapshot.iconURL).ascii().data()); - - m_setIconDataStatement->reset(); - } -} - -} // namespace WebCore diff --git a/WebCore/loader/icon/IconDatabase.h b/WebCore/loader/icon/IconDatabase.h deleted file mode 100644 index 4303ae1..0000000 --- a/WebCore/loader/icon/IconDatabase.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IconDatabase_h -#define IconDatabase_h - -#if ENABLE(ICONDATABASE) -#include "SQLiteDatabase.h" -#endif - -#include "StringHash.h" -#include "Timer.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> -#if ENABLE(ICONDATABASE) -#include <wtf/Threading.h> -#endif - -namespace WebCore { - -class DocumentLoader; -class Image; -class IntSize; -class IconDatabaseClient; -class IconRecord; -class IconSnapshot; -class KURL; -class PageURLRecord; -class PageURLSnapshot; -class SharedBuffer; - -#if ENABLE(ICONDATABASE) -class SQLTransaction; -#endif - -enum IconLoadDecision { - IconLoadYes, - IconLoadNo, - IconLoadUnknown -}; - -class IconDatabase : Noncopyable { - -// *** Main Thread Only *** -public: - void setClient(IconDatabaseClient*); - - bool open(const String& path); - void close(); - - void removeAllIcons(); - - Image* iconForPageURL(const String&, const IntSize&); - void readIconForPageURLFromDisk(const String&); - String iconURLForPageURL(const String&); - Image* defaultIcon(const IntSize&); - - void retainIconForPageURL(const String&); - void releaseIconForPageURL(const String&); - - void setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&); - void setIconURLForPageURL(const String& iconURL, const String& pageURL); - - IconLoadDecision loadDecisionForIconURL(const String&, DocumentLoader*); - bool iconDataKnownForIconURL(const String&); - - void setEnabled(bool enabled); - bool isEnabled() const; - - void setPrivateBrowsingEnabled(bool flag); - bool isPrivateBrowsingEnabled() const; - - static void delayDatabaseCleanup(); - static void allowDatabaseCleanup(); - static void checkIntegrityBeforeOpening(); - - // Support for WebCoreStatistics in WebKit - size_t pageURLMappingCount(); - size_t retainedPageURLCount(); - size_t iconRecordCount(); - size_t iconRecordCountWithData(); - -private: - IconDatabase(); - ~IconDatabase(); - friend IconDatabase* iconDatabase(); - -#if ENABLE(ICONDATABASE) - static void notifyPendingLoadDecisionsOnMainThread(void*); - void notifyPendingLoadDecisions(); - - void wakeSyncThread(); - void scheduleOrDeferSyncTimer(); - OwnPtr<Timer<IconDatabase> > m_syncTimer; - void syncTimerFired(Timer<IconDatabase>*); - - ThreadIdentifier m_syncThread; - bool m_syncThreadRunning; - - HashSet<RefPtr<DocumentLoader> > m_loadersPendingDecision; - - RefPtr<IconRecord> m_defaultIconRecord; -#endif // ENABLE(ICONDATABASE) - -// *** Any Thread *** -public: - bool isOpen() const; - String databasePath() const; - static String defaultDatabaseFilename(); - -#if ENABLE(ICONDATABASE) -private: - PassRefPtr<IconRecord> getOrCreateIconRecord(const String& iconURL); - PageURLRecord* getOrCreatePageURLRecord(const String& pageURL); - - bool m_isEnabled; - bool m_privateBrowsingEnabled; - - mutable Mutex m_syncLock; - ThreadCondition m_syncCondition; - String m_databaseDirectory; - // Holding m_syncLock is required when accessing m_completeDatabasePath - String m_completeDatabasePath; - - bool m_threadTerminationRequested; - bool m_removeIconsRequested; - bool m_iconURLImportComplete; - - Mutex m_urlAndIconLock; - // Holding m_urlAndIconLock is required when accessing any of the following data structures or the objects they contain - HashMap<String, IconRecord*> m_iconURLToRecordMap; - HashMap<String, PageURLRecord*> m_pageURLToRecordMap; - HashSet<String> m_retainedPageURLs; - - Mutex m_pendingSyncLock; - // Holding m_pendingSyncLock is required when accessing any of the following data structures - HashMap<String, PageURLSnapshot> m_pageURLsPendingSync; - HashMap<String, IconSnapshot> m_iconsPendingSync; - - Mutex m_pendingReadingLock; - // Holding m_pendingSyncLock is required when accessing any of the following data structures - when dealing with IconRecord*s, holding m_urlAndIconLock is also required - HashSet<String> m_pageURLsPendingImport; - HashSet<String> m_pageURLsInterestedInIcons; - HashSet<IconRecord*> m_iconsPendingReading; - -// *** Sync Thread Only *** -public: - // Should be used only on the sync thread and only by the Safari 2 Icons import procedure - void importIconURLForPageURL(const String& iconURL, const String& pageURL); - void importIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL); - - bool shouldStopThreadActivity() const; - -private: - static void* iconDatabaseSyncThreadStart(void *); - void* iconDatabaseSyncThread(); - - // The following block of methods are called exclusively by the sync thread to manage i/o to and from the database - // Each method should periodically monitor m_threadTerminationRequested when it makes sense to return early on shutdown - void performOpenInitialization(); - bool checkIntegrity(); - void performURLImport(); - void* syncThreadMainLoop(); - bool readFromDatabase(); - bool writeToDatabase(); - void pruneUnretainedIcons(); - void checkForDanglingPageURLs(bool pruneIfFound); - void removeAllIconsOnThread(); - void deleteAllPreparedStatements(); - void* cleanupSyncThread(); - - // Record (on disk) whether or not Safari 2-style icons were imported (once per dataabse) - bool imported(); - void setImported(bool); - - bool m_initialPruningComplete; - - void setIconURLForPageURLInSQLDatabase(const String&, const String&); - void setIconIDForPageURLInSQLDatabase(int64_t, const String&); - void removePageURLFromSQLDatabase(const String& pageURL); - int64_t getIconIDForIconURLFromSQLDatabase(const String& iconURL); - int64_t addIconURLToSQLDatabase(const String&); - PassRefPtr<SharedBuffer> getImageDataForIconURLFromSQLDatabase(const String& iconURL); - void removeIconFromSQLDatabase(const String& iconURL); - void writeIconSnapshotToSQLDatabase(const IconSnapshot&); - - // The client is set by the main thread before the thread starts, and from then on is only used by the sync thread - IconDatabaseClient* m_client; - - SQLiteDatabase m_syncDB; - - // Track whether the "Safari 2" import is complete and/or set in the database - bool m_imported; - bool m_isImportedSet; - - OwnPtr<SQLiteStatement> m_setIconIDForPageURLStatement; - OwnPtr<SQLiteStatement> m_removePageURLStatement; - OwnPtr<SQLiteStatement> m_getIconIDForIconURLStatement; - OwnPtr<SQLiteStatement> m_getImageDataForIconURLStatement; - OwnPtr<SQLiteStatement> m_addIconToIconInfoStatement; - OwnPtr<SQLiteStatement> m_addIconToIconDataStatement; - OwnPtr<SQLiteStatement> m_getImageDataStatement; - OwnPtr<SQLiteStatement> m_deletePageURLsForIconURLStatement; - OwnPtr<SQLiteStatement> m_deleteIconFromIconInfoStatement; - OwnPtr<SQLiteStatement> m_deleteIconFromIconDataStatement; - OwnPtr<SQLiteStatement> m_updateIconInfoStatement; - OwnPtr<SQLiteStatement> m_updateIconDataStatement; - OwnPtr<SQLiteStatement> m_setIconInfoStatement; - OwnPtr<SQLiteStatement> m_setIconDataStatement; -#endif // ENABLE(ICONDATABASE) -}; - -// Function to obtain the global icon database. -IconDatabase* iconDatabase(); - -} // namespace WebCore - -#endif diff --git a/WebCore/loader/icon/IconDatabaseClient.h b/WebCore/loader/icon/IconDatabaseClient.h deleted file mode 100644 index e642895..0000000 --- a/WebCore/loader/icon/IconDatabaseClient.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IconDatabaseClient_h -#define IconDatabaseClient_h - -// All of these client methods will be called from a non-main thread -// Take appropriate measures - -namespace WebCore { - -class String; - -class IconDatabaseClient { -public: - virtual ~IconDatabaseClient() { } - virtual bool performImport() { return true; } - virtual void dispatchDidRemoveAllIcons() { } - virtual void dispatchDidAddIconForPageURL(const String& pageURL) { } -}; - -} // namespace WebCore -#endif diff --git a/WebCore/loader/icon/IconDatabaseNone.cpp b/WebCore/loader/icon/IconDatabaseNone.cpp deleted file mode 100644 index c76a2c4..0000000 --- a/WebCore/loader/icon/IconDatabaseNone.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconDatabase.h" -#include "SharedBuffer.h" - -namespace WebCore { - -static IconDatabase* sharedIconDatabase = 0; - -// This version number is in the DB and marks the current generation of the schema -// Theoretically once the switch is flipped this should never change -// Currently, an out-of-date schema causes the DB to be wiped and reset. This isn't -// so bad during development but in the future, we would need to write a conversion -// function to advance older released schemas to "current" -const int currentDatabaseVersion = 5; - -// Icons expire once a day -const int iconExpirationTime = 60*60*24; -// Absent icons are rechecked once a week -const int missingIconExpirationTime = 60*60*24*7; - -const int updateTimerDelay = 5; - -String IconDatabase::defaultDatabaseFilename() -{ - static String defaultDatabaseFilename = "Icons.db"; - return defaultDatabaseFilename; -} - -IconDatabase* iconDatabase() -{ - if (!sharedIconDatabase) - sharedIconDatabase = new IconDatabase; - return sharedIconDatabase; -} - -IconDatabase::IconDatabase() -{ -} - -bool IconDatabase::open(const String& databasePath) -{ - return false; -} - -bool IconDatabase::isOpen() const -{ - return false; -} - -void IconDatabase::close() -{ -} - -String IconDatabase::databasePath() const -{ - return String(); -} - -void IconDatabase::removeAllIcons() -{ -} - -void IconDatabase::setPrivateBrowsingEnabled(bool flag) -{ -} - -bool IconDatabase::isPrivateBrowsingEnabled() const -{ - return false; -} - -void IconDatabase::readIconForPageURLFromDisk(const String&) -{ - -} - -Image* IconDatabase::iconForPageURL(const String& pageURL, const IntSize& size) -{ - return defaultIcon(size); -} - - -IconLoadDecision IconDatabase::loadDecisionForIconURL(const String&, DocumentLoader*) -{ - return IconLoadNo; -} - -bool IconDatabase::iconDataKnownForIconURL(const String&) -{ - return false; -} - -String IconDatabase::iconURLForPageURL(const String& pageURL) -{ - return String(); -} - -Image* IconDatabase::defaultIcon(const IntSize& size) -{ - return 0; -} - -void IconDatabase::retainIconForPageURL(const String& pageURL) -{ -} - -void IconDatabase::releaseIconForPageURL(const String& pageURL) -{ -} - -void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String& iconURL) -{ -} - -void IconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL) -{ -} - -void IconDatabase::setEnabled(bool enabled) -{ -} - -bool IconDatabase::isEnabled() const -{ - return false; -} - -IconDatabase::~IconDatabase() -{ - ASSERT_NOT_REACHED(); -} - -void IconDatabase::checkIntegrityBeforeOpening() -{ -} - -void IconDatabase::delayDatabaseCleanup() -{ -} - -void IconDatabase::allowDatabaseCleanup() -{ -} - -void IconDatabase::setClient(IconDatabaseClient*) -{ -} - -} // namespace WebCore diff --git a/WebCore/loader/icon/IconFetcher.cpp b/WebCore/loader/icon/IconFetcher.cpp deleted file mode 100644 index efa7e14..0000000 --- a/WebCore/loader/icon/IconFetcher.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconFetcher.h" - -#include "Document.h" -#include "Frame.h" -#include "HTMLHeadElement.h" -#include "HTMLLinkElement.h" -#include "HTMLNames.h" -#include "MIMETypeRegistry.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "SharedBuffer.h" -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -using namespace HTMLNames; - -struct IconLinkEntry { -public: - enum IconType { - Unknown, - ICNS, - ICO, - }; - - IconLinkEntry(IconType type, const KURL& url) - : m_type(type) - , m_url(url) - { - } - - IconType type() const { return m_type; } - const KURL& url() const { return m_url; } - - SharedBuffer* buffer() - { - if (!m_buffer) - m_buffer = SharedBuffer::create(); - - return m_buffer.get(); - } - -private: - RefPtr<SharedBuffer> m_buffer; - IconType m_type; - KURL m_url; -}; - -#if PLATFORM(MAC) -static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::ICNS; -#elif PLATFORM(WIN) -static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::ICO; -#else -static const IconLinkEntry::IconType NativeIconType = IconLinkEntry::Unknown; -#endif - -static void parseIconLink(HTMLLinkElement* link, Vector<IconLinkEntry>& entries) -{ - // FIXME: Parse the size attribute too. - - IconLinkEntry::IconType type = IconLinkEntry::Unknown; - const KURL& url = link->href(); - - // Try to determine the file type. - String path = url.path(); - - int pos = path.reverseFind('.'); - if (pos >= 0) { - String extension = path.substring(pos + 1); - if (equalIgnoringCase(extension, "icns")) - type = IconLinkEntry::ICNS; - else if (equalIgnoringCase(extension, "ico")) - type = IconLinkEntry::ICO; - } - - entries.append(IconLinkEntry(type, url)); -} - -PassRefPtr<IconFetcher> IconFetcher::create(Frame* frame, IconFetcherClient* client) -{ - Document* document = frame->document(); - if (!document) - return 0; - - HTMLHeadElement* head = document->head(); - if (!head) - return 0; - - Vector<IconLinkEntry> entries; - - for (Node* n = head; n; n = n->traverseNextNode()) { - if (!n->hasTagName(linkTag)) - continue; - - HTMLLinkElement* link = static_cast<HTMLLinkElement*>(n); - if (!link->isIcon()) - continue; - - parseIconLink(link, entries); - } - - if (entries.isEmpty()) - return 0; - - // Check if any of the entries have the same type as the native icon type. - - // FIXME: This should be way more sophisticated, and handle conversion - // of multisize formats for example. - for (unsigned i = 0; i < entries.size(); i++) { - const IconLinkEntry& entry = entries[i]; - if (entry.type() == NativeIconType) { - RefPtr<IconFetcher> iconFetcher = adoptRef(new IconFetcher(frame, client)); - - iconFetcher->m_entries.append(entry); - iconFetcher->loadEntry(); - - return iconFetcher.release(); - } - } - - return 0; -} - -IconFetcher::IconFetcher(Frame* frame, IconFetcherClient* client) - : m_frame(frame) - , m_client(client) - , m_currentEntry(0) -{ -} - -IconFetcher::~IconFetcher() -{ - cancel(); -} - -void IconFetcher::cancel() -{ - if (m_handle) - m_handle->cancel(); -} - -PassRefPtr<SharedBuffer> IconFetcher::createIcon() -{ - ASSERT(!m_entries.isEmpty()); - - // For now, just return the data of the first entry. - return m_entries.first().buffer(); -} - - -void IconFetcher::loadEntry() -{ - ASSERT(m_currentEntry < m_entries.size()); - ASSERT(!m_handle); - - m_handle = ResourceHandle::create(m_entries[m_currentEntry].url(), this, m_frame, false, false); -} - -void IconFetcher::loadFailed() -{ - m_handle = 0; - - m_client->finishedFetchingIcon(0); -} - -void IconFetcher::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response) -{ - ASSERT(m_handle == handle); - - int statusCode = response.httpStatusCode() / 100; - if (statusCode == 4 || statusCode == 5) { - loadFailed(); - return; - } -} - -void IconFetcher::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived) -{ - ASSERT(m_handle == handle); - - m_entries[m_currentEntry].buffer()->append(data, length); -} - -void IconFetcher::didFinishLoading(ResourceHandle* handle) -{ - ASSERT(m_handle == handle); - - if (m_currentEntry == m_entries.size() - 1) { - // We finished loading, create the icon - RefPtr<SharedBuffer> iconData = createIcon(); - - m_client->finishedFetchingIcon(iconData.release()); - return; - } - - // Load the next entry - m_currentEntry++; - - loadEntry(); -} - -void IconFetcher::didFail(ResourceHandle* handle, const ResourceError&) -{ - ASSERT(m_handle == handle); - - loadFailed(); -} - - -} // namespace WebCore diff --git a/WebCore/loader/icon/IconFetcher.h b/WebCore/loader/icon/IconFetcher.h deleted file mode 100644 index 5327693..0000000 --- a/WebCore/loader/icon/IconFetcher.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IconFetcher_h -#define IconFetcher_h - -#include <wtf/RefCounted.h> -#include <wtf/Forward.h> -#include <wtf/Vector.h> - -#include "ResourceHandleClient.h" - -namespace WebCore { - -class Frame; -struct IconLinkEntry; -class ResourceHandle; -class SharedBuffer; - -class IconFetcherClient { -public: - virtual void finishedFetchingIcon(PassRefPtr<SharedBuffer> iconData) = 0; - - virtual ~IconFetcherClient() { } -}; - -class IconFetcher : public RefCounted<IconFetcher>, ResourceHandleClient { -public: - static PassRefPtr<IconFetcher> create(Frame*, IconFetcherClient*); - ~IconFetcher(); - - void cancel(); - -private: - IconFetcher(Frame*, IconFetcherClient*); - void loadEntry(); - void loadFailed(); - - PassRefPtr<SharedBuffer> createIcon(); - - virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); - virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived); - virtual void didFinishLoading(ResourceHandle*); - virtual void didFail(ResourceHandle*, const ResourceError&); - - Frame* m_frame; - IconFetcherClient* m_client; - - unsigned m_currentEntry; - RefPtr<ResourceHandle> m_handle; - Vector<IconLinkEntry> m_entries; -}; - -} // namespace WebCore - -#endif // IconFetcher_h diff --git a/WebCore/loader/icon/IconLoader.cpp b/WebCore/loader/icon/IconLoader.cpp deleted file mode 100644 index 4337f51..0000000 --- a/WebCore/loader/icon/IconLoader.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconLoader.h" - -#include "Document.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "IconDatabase.h" -#include "Logging.h" -#include "ResourceHandle.h" -#include "ResourceResponse.h" -#include "ResourceRequest.h" -#include "SubresourceLoader.h" - -using namespace std; - -namespace WebCore { - -IconLoader::IconLoader(Frame* frame) - : m_frame(frame) - , m_loadIsInProgress(false) -{ -} - -auto_ptr<IconLoader> IconLoader::create(Frame* frame) -{ - return auto_ptr<IconLoader>(new IconLoader(frame)); -} - -IconLoader::~IconLoader() -{ -} - -void IconLoader::startLoading() -{ - if (m_resourceLoader) - return; - - // FIXME: http://bugs.webkit.org/show_bug.cgi?id=10902 - // Once ResourceHandle will load without a DocLoader, we can remove this check. - // A frame may be documentless - one example is a frame containing only a PDF. - if (!m_frame->document()) { - LOG(IconDatabase, "Documentless-frame - icon won't be loaded"); - return; - } - - // Set flag so we can detect the case where the load completes before - // SubresourceLoader::create returns. - m_loadIsInProgress = true; - - RefPtr<SubresourceLoader> loader = SubresourceLoader::create(m_frame, this, m_frame->loader()->iconURL()); - if (!loader) - LOG_ERROR("Failed to start load for icon at url %s", m_frame->loader()->iconURL().string().ascii().data()); - - // Store the handle so we can cancel the load if stopLoading is called later. - // But only do it if the load hasn't already completed. - if (m_loadIsInProgress) - m_resourceLoader = loader.release(); -} - -void IconLoader::stopLoading() -{ - clearLoadingState(); -} - -void IconLoader::didReceiveResponse(SubresourceLoader* resourceLoader, const ResourceResponse& response) -{ - // If we got a status code indicating an invalid response, then lets - // ignore the data and not try to decode the error page as an icon. - int status = response.httpStatusCode(); - LOG(IconDatabase, "IconLoader::didReceiveResponse() - Loader %p, response %i", resourceLoader, status); - - if (status && (status < 200 || status > 299)) { - ResourceHandle* handle = resourceLoader->handle(); - finishLoading(handle ? handle->request().url() : KURL(), 0); - } -} - -void IconLoader::didReceiveData(SubresourceLoader* loader, const char*, int size) -{ - LOG(IconDatabase, "IconLoader::didReceiveData() - Loader %p, number of bytes %i", loader, size); -} - -void IconLoader::didFail(SubresourceLoader* resourceLoader, const ResourceError&) -{ - LOG(IconDatabase, "IconLoader::didFail() - Loader %p", resourceLoader); - - // Until <rdar://problem/5463392> is resolved and we can properly cancel SubresourceLoaders when they get an error response, - // we need to be prepared to receive this call even after we've "finished loading" once. - // After it is resolved, we can restore an assertion that the load is in progress if ::didFail() is called - - if (m_loadIsInProgress) { - ASSERT(resourceLoader == m_resourceLoader); - ResourceHandle* handle = resourceLoader->handle(); - finishLoading(handle ? handle->request().url() : KURL(), 0); - } -} - -void IconLoader::didReceiveAuthenticationChallenge(SubresourceLoader* resourceLoader, const AuthenticationChallenge& challenge) -{ - // We don't ever want to prompt for authentication just for a site icon, so - // implement this method to cancel the resource load - m_resourceLoader->cancel(); -} - -void IconLoader::didFinishLoading(SubresourceLoader* resourceLoader) -{ - LOG(IconDatabase, "IconLoader::didFinishLoading() - Loader %p", resourceLoader); - - // Until <rdar://problem/5463392> is resolved and we can properly cancel SubresourceLoaders when they get an error response, - // we need to be prepared to receive this call even after we've "finished loading" once. - // After it is resolved, we can restore an assertion that the load is in progress if ::didFail() is called - - if (m_loadIsInProgress) { - ASSERT(resourceLoader == m_resourceLoader); - ResourceHandle* handle = resourceLoader->handle(); - finishLoading(handle ? handle->request().url() : KURL(), m_resourceLoader->resourceData()); - } -} - -void IconLoader::finishLoading(const KURL& iconURL, PassRefPtr<SharedBuffer> data) -{ - // When an icon load results in a 404 we commit it to the database here and clear the loading state. - // But the SubresourceLoader continues pulling in data in the background for the 404 page if the server sends one. - // Once that data finishes loading or if the load is cancelled while that data is being read, finishLoading ends up being called a second time. - // We need to change SubresourceLoader to have a mode where it will stop itself after receiving a 404 so this won't happen - - // in the meantime, we'll only commit this data to the IconDatabase if it's the first time ::finishLoading() is called - // <rdar://problem/5463392> tracks that enhancement - - if (!iconURL.isEmpty() && m_loadIsInProgress) { - iconDatabase()->setIconDataForIconURL(data, iconURL.string()); - LOG(IconDatabase, "IconLoader::finishLoading() - Committing iconURL %s to database", iconURL.string().ascii().data()); - m_frame->loader()->commitIconURLToIconDatabase(iconURL); - m_frame->loader()->client()->dispatchDidReceiveIcon(); - } - - clearLoadingState(); -} - -void IconLoader::clearLoadingState() -{ - m_resourceLoader = 0; - m_loadIsInProgress = false; -} - -} diff --git a/WebCore/loader/icon/IconLoader.h b/WebCore/loader/icon/IconLoader.h deleted file mode 100644 index a7194d8..0000000 --- a/WebCore/loader/icon/IconLoader.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IconLoader_h -#define IconLoader_h - -#include "SubresourceLoaderClient.h" -#include <memory> -#include <wtf/Forward.h> -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; -class KURL; -class SharedBuffer; - -class IconLoader : private SubresourceLoaderClient, Noncopyable { -public: - static std::auto_ptr<IconLoader> create(Frame*); - ~IconLoader(); - - void startLoading(); - void stopLoading(); - -private: - IconLoader(Frame*); - - virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&); - virtual void didReceiveData(SubresourceLoader*, const char*, int); - virtual void didFinishLoading(SubresourceLoader*); - virtual void didFail(SubresourceLoader*, const ResourceError&); - - virtual void didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&); - - void finishLoading(const KURL&, PassRefPtr<SharedBuffer> data); - void clearLoadingState(); - - Frame* m_frame; - - RefPtr<SubresourceLoader> m_resourceLoader; - bool m_loadIsInProgress; -}; // class IconLoader - -} // namespace WebCore - -#endif diff --git a/WebCore/loader/icon/IconRecord.cpp b/WebCore/loader/icon/IconRecord.cpp deleted file mode 100644 index f070cc9..0000000 --- a/WebCore/loader/icon/IconRecord.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "IconRecord.h" - -#include "BitmapImage.h" -#include "IconDatabase.h" -#include "Logging.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" -#include "SystemTime.h" - -#include <limits.h> - -namespace WebCore { - -IconRecord::IconRecord(const String& url) - : m_iconURL(url) - , m_stamp(0) - , m_dataSet(false) -{ - -} - -IconRecord::~IconRecord() -{ - LOG(IconDatabase, "Destroying IconRecord for icon url %s", m_iconURL.ascii().data()); -} - -Image* IconRecord::image(const IntSize& size) -{ - // FIXME rdar://4680377 - For size right now, we are returning our one and only image and the Bridge - // is resizing it in place. We need to actually store all the original representations here and return a native - // one, or resize the best one to the requested size and cache that result. - - return m_image.get(); -} - -void IconRecord::setImageData(PassRefPtr<SharedBuffer> data) -{ - // It's okay to delete the raw image here. Any existing clients using this icon will be - // managing an image that was created with a copy of this raw image data. - m_image = BitmapImage::create(); - - // Copy the provided data into the buffer of the new Image object. - if (!m_image->setData(data, true)) { - LOG(IconDatabase, "Manual image data for iconURL '%s' FAILED - it was probably invalid image data", m_iconURL.ascii().data()); - m_image.clear(); - } - - m_dataSet = true; -} - -void IconRecord::loadImageFromResource(const char* resource) -{ - if (!resource) - return; - - m_image = Image::loadPlatformResource(resource); - m_dataSet = true; -} - -ImageDataStatus IconRecord::imageDataStatus() -{ - if (!m_dataSet) - return ImageDataStatusUnknown; - if (!m_image) - return ImageDataStatusMissing; - return ImageDataStatusPresent; -} - -IconSnapshot IconRecord::snapshot(bool forDeletion) const -{ - if (forDeletion) - return IconSnapshot(m_iconURL, 0, 0); - - return IconSnapshot(m_iconURL, m_stamp, m_image ? m_image->data() : 0); -} - -} // namespace WebCore diff --git a/WebCore/loader/icon/IconRecord.h b/WebCore/loader/icon/IconRecord.h deleted file mode 100644 index aaea787..0000000 --- a/WebCore/loader/icon/IconRecord.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef IconRecord_h -#define IconRecord_h - -#include "PageURLRecord.h" -#include <wtf/RefCounted.h> -#include "SharedBuffer.h" - -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#include "PlatformString.h" -#include "StringHash.h" - -namespace WebCore { - -class IconDataSnapshot; -class Image; -class IntSize; -class SQLDatabase; - -enum ImageDataStatus { - ImageDataStatusPresent, ImageDataStatusMissing, ImageDataStatusUnknown -}; - -class IconSnapshot { -public: - IconSnapshot() : timestamp(0) { } - - IconSnapshot(const String& url, int stamp, SharedBuffer* theData) - : iconURL(url) - , timestamp(stamp) - , data(theData) - { } - - String iconURL; - int timestamp; - RefPtr<SharedBuffer> data; -}; - -class IconRecord : public RefCounted<IconRecord> { - friend class PageURLRecord; -public: - static PassRefPtr<IconRecord> create(const String& url) - { - return adoptRef(new IconRecord(url)); - } - ~IconRecord(); - - time_t getTimestamp() { return m_stamp; } - void setTimestamp(time_t stamp) { m_stamp = stamp; } - - void setImageData(PassRefPtr<SharedBuffer> data); - Image* image(const IntSize&); - - String iconURL() { return m_iconURL; } - - void loadImageFromResource(const char*); - - ImageDataStatus imageDataStatus(); - - const HashSet<String>& retainingPageURLs() { return m_retainingPageURLs; } - - IconSnapshot snapshot(bool forDeletion = false) const; - -private: - IconRecord(const String& url); - - String m_iconURL; - time_t m_stamp; - RefPtr<Image> m_image; - - HashSet<String> m_retainingPageURLs; - - // This allows us to cache whether or not a SiteIcon has had its data set yet - // This helps the IconDatabase know if it has to set the data on a new object or not, - // and also to determine if the icon is missing data or if it just hasn't been brought - // in from the DB yet - bool m_dataSet; - - // FIXME - Right now WebCore::Image doesn't have a very good API for accessing multiple representations - // Even the NSImage way of doing things that we do in WebKit isn't very clean... once we come up with a - // better way of handling that, we'll likely have a map of size-to-images similar to below - // typedef HashMap<IntSize, Image*> SizeImageMap; - // SizeImageMap m_images; -}; - - -} //namespace WebCore - -#endif diff --git a/WebCore/loader/icon/PageURLRecord.cpp b/WebCore/loader/icon/PageURLRecord.cpp deleted file mode 100644 index 09d649f..0000000 --- a/WebCore/loader/icon/PageURLRecord.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "PageURLRecord.h" - -#include "IconRecord.h" - -namespace WebCore { - -PageURLRecord::PageURLRecord(const String& pageURL) - : m_pageURL(pageURL) - , m_retainCount(0) -{ -} - -PageURLRecord::~PageURLRecord() -{ - setIconRecord(0); -} - -void PageURLRecord::setIconRecord(PassRefPtr<IconRecord> icon) -{ - if (m_iconRecord) - m_iconRecord->m_retainingPageURLs.remove(m_pageURL); - - m_iconRecord = icon; - - if (m_iconRecord) - m_iconRecord->m_retainingPageURLs.add(m_pageURL); -} - -PageURLSnapshot PageURLRecord::snapshot(bool forDeletion) const -{ - return PageURLSnapshot(m_pageURL, (m_iconRecord && !forDeletion) ? m_iconRecord->iconURL() : String()); -} - -} // namespace WebCore diff --git a/WebCore/loader/icon/PageURLRecord.h b/WebCore/loader/icon/PageURLRecord.h deleted file mode 100644 index bc52f5b..0000000 --- a/WebCore/loader/icon/PageURLRecord.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PageURLRecord_h -#define PageURLRecord_h - -#include "PlatformString.h" - -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class IconRecord; - -class PageURLSnapshot { -public: - PageURLSnapshot() { } - - PageURLSnapshot(const String& page, const String& icon) - : pageURL(page) - , iconURL(icon) - { } - - String pageURL; - String iconURL; -}; - -class PageURLRecord : Noncopyable { -public: - PageURLRecord(const String& pageURL); - ~PageURLRecord(); - - inline String url() const { return m_pageURL; } - - void setIconRecord(PassRefPtr<IconRecord>); - IconRecord* iconRecord() { return m_iconRecord.get(); } - - PageURLSnapshot snapshot(bool forDeletion = false) const; - - // Returns false if the page wasn't retained beforehand, true if the retain count was already 1 or higher - inline bool retain() { return m_retainCount++; } - - // Returns true if the page is still retained after the call. False if the retain count just dropped to 0 - inline bool release() - { - ASSERT(m_retainCount > 0); - return --m_retainCount; - } - - inline int retainCount() const { return m_retainCount; } -private: - String m_pageURL; - RefPtr<IconRecord> m_iconRecord; - int m_retainCount; -}; - -} - -#endif // PageURLRecord_h diff --git a/WebCore/loader/loader.cpp b/WebCore/loader/loader.cpp deleted file mode 100644 index 6221a6a..0000000 --- a/WebCore/loader/loader.cpp +++ /dev/null @@ -1,495 +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) 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 "loader.h" - -#include "Cache.h" -#include "CachedImage.h" -#include "CachedResource.h" -#include "CString.h" -#include "DocLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "HTMLDocument.h" -#include "Request.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "SecurityOrigin.h" -#include "SubresourceLoader.h" -#include <wtf/Assertions.h> -#include <wtf/Vector.h> - -#define REQUEST_MANAGEMENT_ENABLED 0 -#define REQUEST_DEBUG 0 - -namespace WebCore { - -#if REQUEST_MANAGEMENT_ENABLED -// Match the parallel connection count used by the networking layer -// FIXME should not hardcode something like this -static const unsigned maxRequestsInFlightPerHost = 4; -// Having a limit might still help getting more important resources first -static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20; -#else -static const unsigned maxRequestsInFlightPerHost = 10000; -static const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000; -#endif - - -Loader::Loader() - : m_nonHTTPProtocolHost(AtomicString(), maxRequestsInFlightForNonHTTPProtocols) - , m_requestTimer(this, &Loader::requestTimerFired) -{ -} - -Loader::~Loader() -{ - ASSERT_NOT_REACHED(); -} - -Loader::Priority Loader::determinePriority(const CachedResource* resource) const -{ -#if REQUEST_MANAGEMENT_ENABLED - switch (resource->type()) { - case CachedResource::CSSStyleSheet: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif -#if ENABLE(XBL) - case CachedResource::XBL: -#endif - return High; - case CachedResource::Script: - case CachedResource::FontResource: - return Medium; - case CachedResource::ImageResource: - return Low; - } - ASSERT_NOT_REACHED(); - return Low; -#else - return High; -#endif -} - -void Loader::load(DocLoader* docLoader, CachedResource* resource, bool incremental, bool skipCanLoadCheck, bool sendResourceLoadCallbacks) -{ - ASSERT(docLoader); - Request* request = new Request(docLoader, resource, incremental, skipCanLoadCheck, sendResourceLoadCallbacks); - - Host* host; - KURL url(resource->url()); - bool isHTTP = url.protocolIs("http") || url.protocolIs("https"); - if (isHTTP) { - AtomicString hostName = url.host(); - host = m_hosts.get(hostName.impl()); - if (!host) { - host = new Host(hostName, maxRequestsInFlightPerHost); - m_hosts.add(hostName.impl(), host); - } - } else - host = &m_nonHTTPProtocolHost; - - bool hadRequests = host->hasRequests(); - Priority priority = determinePriority(resource); - host->addRequest(request, priority); - docLoader->incrementRequestCount(); - - if (priority > Low || !isHTTP || !hadRequests) { - // Try to request important resources immediately - host->servePendingRequests(priority); - } else { - // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones - scheduleServePendingRequests(); - } -} - -void Loader::scheduleServePendingRequests() -{ - if (!m_requestTimer.isActive()) - m_requestTimer.startOneShot(0); -} - -void Loader::requestTimerFired(Timer<Loader>*) -{ - servePendingRequests(); -} - -void Loader::servePendingRequests(Priority minimumPriority) -{ - m_requestTimer.stop(); - - m_nonHTTPProtocolHost.servePendingRequests(minimumPriority); - - Vector<Host*> hostsToServe; - copyValuesToVector(m_hosts, hostsToServe); - for (unsigned n = 0; n < hostsToServe.size(); ++n) { - Host* host = hostsToServe[n]; - if (host->hasRequests()) - host->servePendingRequests(minimumPriority); - else if (!host->processingResource()){ - AtomicString name = host->name(); - delete host; - m_hosts.remove(name.impl()); - } - } -} - -void Loader::cancelRequests(DocLoader* docLoader) -{ - if (m_nonHTTPProtocolHost.hasRequests()) - m_nonHTTPProtocolHost.cancelRequests(docLoader); - - Vector<Host*> hostsToCancel; - copyValuesToVector(m_hosts, hostsToCancel); - for (unsigned n = 0; n < hostsToCancel.size(); ++n) { - Host* host = hostsToCancel[n]; - if (host->hasRequests()) - host->cancelRequests(docLoader); - } - - scheduleServePendingRequests(); - - if (docLoader->loadInProgress()) - ASSERT(docLoader->requestCount() == 1); - else - ASSERT(docLoader->requestCount() == 0); -} - -Loader::Host::Host(const AtomicString& name, unsigned maxRequestsInFlight) - : m_name(name) - , m_maxRequestsInFlight(maxRequestsInFlight) - , m_processingResource(false) -{ -} - -Loader::Host::~Host() -{ - ASSERT(m_requestsLoading.isEmpty()); - for (unsigned p = 0; p <= High; p++) - ASSERT(m_requestsPending[p].isEmpty()); -} - -void Loader::Host::addRequest(Request* request, Priority priority) -{ - m_requestsPending[priority].append(request); -} - -bool Loader::Host::hasRequests() const -{ - if (!m_requestsLoading.isEmpty()) - return true; - for (unsigned p = 0; p <= High; p++) { - if (!m_requestsPending[p].isEmpty()) - return true; - } - return false; -} - -void Loader::Host::servePendingRequests(Loader::Priority minimumPriority) -{ - bool serveMore = true; - for (int priority = High; priority >= minimumPriority && serveMore; --priority) - servePendingRequests(m_requestsPending[priority], serveMore); -} - -void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority) -{ - while (!requestsPending.isEmpty()) { - Request* request = requestsPending.first(); - DocLoader* docLoader = request->docLoader(); - bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); - // If the document is fully parsed and there are no pending stylesheets there won't be any more - // resources that we would want to push to the front of the queue. Just hand off the remaining resources - // to the networking layer. - bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded(); - if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) { - serveLowerPriority = false; - return; - } - requestsPending.removeFirst(); - - ResourceRequest resourceRequest(request->cachedResource()->url()); -#ifdef ANDROID - resourceRequest.setCachedResource(request->cachedResource()); -#endif - - if (!request->cachedResource()->accept().isEmpty()) - resourceRequest.setHTTPAccept(request->cachedResource()->accept()); - - KURL referrer = docLoader->doc()->url(); - if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty()) - referrer.setPath("/"); - resourceRequest.setHTTPReferrer(referrer.string()); - FrameLoader::addHTTPOriginIfNeeded(resourceRequest, docLoader->doc()->securityOrigin()->toString()); - - if (resourceIsCacheValidator) { - CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); - ASSERT(resourceToRevalidate->canUseCacheValidator()); - ASSERT(resourceToRevalidate->isLoaded()); - const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); - const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); - if (!lastModified.isEmpty() || !eTag.isEmpty()) { - if (docLoader->cachePolicy() == CachePolicyReload || docLoader->cachePolicy() == CachePolicyRefresh) - resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); - if (!lastModified.isEmpty()) - resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); - if (!eTag.isEmpty()) - resourceRequest.setHTTPHeaderField("If-None-Match", eTag); - } - } - - RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), - this, resourceRequest, request->shouldSkipCanLoadCheck(), request->sendResourceLoadCallbacks()); - if (loader) { - m_requestsLoading.add(loader.release(), request); - request->cachedResource()->setRequestedFromNetworkingLayer(); -#if REQUEST_DEBUG - printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); -#endif - } else { - docLoader->decrementRequestCount(); - docLoader->setLoadInProgress(true); - request->cachedResource()->error(); - docLoader->setLoadInProgress(false); - delete request; - } - } -} - -void Loader::Host::didFinishLoading(SubresourceLoader* loader) -{ - RequestMap::iterator i = m_requestsLoading.find(loader); - if (i == m_requestsLoading.end()) - return; - - m_processingResource = true; - - Request* request = i->second; - m_requestsLoading.remove(i); - DocLoader* docLoader = request->docLoader(); - if (!request->isMultipart()) - docLoader->decrementRequestCount(); - - CachedResource* resource = request->cachedResource(); - ASSERT(!resource->resourceToRevalidate()); - - // If we got a 4xx response, we're pretending to have received a network - // error, so we can't send the successful data() and finish() callbacks. - if (!resource->errorOccurred()) { - docLoader->setLoadInProgress(true); - resource->data(loader->resourceData(), true); - resource->finish(); - } - - delete request; - - docLoader->setLoadInProgress(false); - - docLoader->checkForPendingPreloads(); - -#if REQUEST_DEBUG - KURL u(resource->url()); - printf("HOST %s COUNT %d RECEIVED %s\n", u.host().latin1().data(), m_requestsLoading.size(), resource->url().latin1().data()); -#endif - servePendingRequests(); - - m_processingResource = false; -} - -void Loader::Host::didFail(SubresourceLoader* loader, const ResourceError&) -{ - didFail(loader); -} - -void Loader::Host::didFail(SubresourceLoader* loader, bool cancelled) -{ - loader->clearClient(); - - RequestMap::iterator i = m_requestsLoading.find(loader); - if (i == m_requestsLoading.end()) - return; - - m_processingResource = true; - - Request* request = i->second; - m_requestsLoading.remove(i); - DocLoader* docLoader = request->docLoader(); - if (!request->isMultipart()) - docLoader->decrementRequestCount(); - - CachedResource* resource = request->cachedResource(); - - if (resource->resourceToRevalidate()) - cache()->revalidationFailed(resource); - - if (!cancelled) { - docLoader->setLoadInProgress(true); - resource->error(); - } - - docLoader->setLoadInProgress(false); - if (cancelled || !resource->isPreloaded()) - cache()->remove(resource); - - delete request; - - docLoader->checkForPendingPreloads(); - - servePendingRequests(); - - m_processingResource = false; -} - -void Loader::Host::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response) -{ - Request* request = m_requestsLoading.get(loader); - - // FIXME: This is a workaround for <rdar://problem/5236843> - // If a load starts while the frame is still in the provisional state - // (this can be the case when loading the user style sheet), committing the load then causes all - // requests to be removed from the m_requestsLoading map. This means that request might be null here. - // In that case we just return early. - // ASSERT(request); - if (!request) - return; - - CachedResource* resource = request->cachedResource(); - - if (resource->isCacheValidator()) { - if (response.httpStatusCode() == 304) { - // 304 Not modified / Use local copy - m_requestsLoading.remove(loader); - request->docLoader()->decrementRequestCount(); - - // Existing resource is ok, just use it updating the expiration time. - cache()->revalidationSucceeded(resource, response); - - if (request->docLoader()->frame()) - request->docLoader()->frame()->loader()->checkCompleted(); - - delete request; - - servePendingRequests(); - return; - } - // Did not get 304 response, continue as a regular resource load. - cache()->revalidationFailed(resource); - } - - resource->setResponse(response); - - String encoding = response.textEncodingName(); - if (!encoding.isNull()) - request->cachedResource()->setEncoding(encoding); - - if (request->isMultipart()) { - ASSERT(request->cachedResource()->isImage()); - static_cast<CachedImage*>(request->cachedResource())->clear(); - if (request->docLoader()->frame()) - request->docLoader()->frame()->loader()->checkCompleted(); - } else if (response.isMultipart()) { - request->setIsMultipart(true); - - // We don't count multiParts in a DocLoader's request count - request->docLoader()->decrementRequestCount(); - - // If we get a multipart response, we must have a handle - ASSERT(loader->handle()); - if (!request->cachedResource()->isImage()) - loader->handle()->cancel(); - } -} - -void Loader::Host::didReceiveData(SubresourceLoader* loader, const char* data, int size) -{ - Request* request = m_requestsLoading.get(loader); - if (!request) - return; - - CachedResource* resource = request->cachedResource(); - ASSERT(!resource->isCacheValidator()); - - if (resource->errorOccurred()) - return; - - m_processingResource = true; - - if (resource->response().httpStatusCode() / 100 == 4) { - // Treat a 4xx response like a network error. - resource->error(); - m_processingResource = false; - return; - } - - // Set the data. - if (request->isMultipart()) { - // The loader delivers the data in a multipart section all at once, send eof. - // The resource data will change as the next part is loaded, so we need to make a copy. - RefPtr<SharedBuffer> copiedData = SharedBuffer::create(data, size); - resource->data(copiedData.release(), true); - } else if (request->isIncremental()) - resource->data(loader->resourceData(), false); - - m_processingResource = false; -} - -void Loader::Host::cancelPendingRequests(RequestQueue& requestsPending, DocLoader* docLoader) -{ - RequestQueue remaining; - RequestQueue::iterator end = requestsPending.end(); - for (RequestQueue::iterator it = requestsPending.begin(); it != end; ++it) { - Request* request = *it; - if (request->docLoader() == docLoader) { - cache()->remove(request->cachedResource()); - delete request; - docLoader->decrementRequestCount(); - } else - remaining.append(request); - } - requestsPending.swap(remaining); -} - -void Loader::Host::cancelRequests(DocLoader* docLoader) -{ - for (unsigned p = 0; p <= High; p++) - cancelPendingRequests(m_requestsPending[p], docLoader); - - Vector<SubresourceLoader*, 256> loadersToCancel; - - RequestMap::iterator end = m_requestsLoading.end(); - for (RequestMap::iterator i = m_requestsLoading.begin(); i != end; ++i) { - Request* r = i->second; - if (r->docLoader() == docLoader) - loadersToCancel.append(i->first.get()); - } - - for (unsigned i = 0; i < loadersToCancel.size(); ++i) { - SubresourceLoader* loader = loadersToCancel[i]; - didFail(loader, true); - } -} - -} //namespace WebCore diff --git a/WebCore/loader/loader.h b/WebCore/loader/loader.h deleted file mode 100644 index c51374c..0000000 --- a/WebCore/loader/loader.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller <mueller@kde.org> - Copyright (C) 2004, 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. -*/ - -#ifndef loader_h -#define loader_h - -#include "AtomicString.h" -#include "AtomicStringImpl.h" -#include "PlatformString.h" -#include "SubresourceLoaderClient.h" -#include "Timer.h" -#include <wtf/Deque.h> -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> - -namespace WebCore { - - class CachedResource; - class DocLoader; - class Request; - - class Loader : Noncopyable { - public: - Loader(); - ~Loader(); - - void load(DocLoader*, CachedResource*, bool incremental = true, bool skipCanLoadCheck = false, bool sendResourceLoadCallbacks = true); - - void cancelRequests(DocLoader*); - - enum Priority { Low, Medium, High }; - void servePendingRequests(Priority minimumPriority = Low); - - private: - Priority determinePriority(const CachedResource*) const; - void scheduleServePendingRequests(); - - void requestTimerFired(Timer<Loader>*); - - class Host : private SubresourceLoaderClient { - public: - Host(const AtomicString& name, unsigned maxRequestsInFlight); - ~Host(); - - const AtomicString& name() const { return m_name; } - void addRequest(Request*, Priority); - void servePendingRequests(Priority minimumPriority = Low); - void cancelRequests(DocLoader*); - bool hasRequests() const; - bool processingResource() const { return m_processingResource; } - - private: - virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&); - virtual void didReceiveData(SubresourceLoader*, const char*, int); - virtual void didFinishLoading(SubresourceLoader*); - virtual void didFail(SubresourceLoader*, const ResourceError&); - - typedef Deque<Request*> RequestQueue; - void servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority); - void didFail(SubresourceLoader*, bool cancelled = false); - void cancelPendingRequests(RequestQueue& requestsPending, DocLoader*); - - RequestQueue m_requestsPending[High + 1]; - typedef HashMap<RefPtr<SubresourceLoader>, Request*> RequestMap; - RequestMap m_requestsLoading; - const AtomicString m_name; - const int m_maxRequestsInFlight; - bool m_processingResource; - }; - typedef HashMap<AtomicStringImpl*, Host*> HostMap; - HostMap m_hosts; - Host m_nonHTTPProtocolHost; - - Timer<Loader> m_requestTimer; - }; - -} - -#endif diff --git a/WebCore/loader/mac/DocumentLoaderMac.cpp b/WebCore/loader/mac/DocumentLoaderMac.cpp deleted file mode 100644 index 05c6e26..0000000 --- a/WebCore/loader/mac/DocumentLoaderMac.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DocumentLoader.h" -#include "MainResourceLoader.h" -#include "ResourceHandle.h" -#include "ResourceLoader.h" - -namespace WebCore { - -#ifndef BUILDING_ON_TIGER -static void scheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair) -{ - const ResourceLoaderSet copy = loaders; - ResourceLoaderSet::const_iterator end = copy.end(); - for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it) - if (ResourceHandle* handle = (*it)->handle()) - handle->schedule(pair); -} - -static void unscheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair) -{ - const ResourceLoaderSet copy = loaders; - ResourceLoaderSet::const_iterator end = copy.end(); - for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it) - if (ResourceHandle* handle = (*it)->handle()) - handle->unschedule(pair); -} -#endif - -void DocumentLoader::schedule(SchedulePair* pair) -{ -#ifndef BUILDING_ON_TIGER - if (m_mainResourceLoader && m_mainResourceLoader->handle()) - m_mainResourceLoader->handle()->schedule(pair); - scheduleAll(m_subresourceLoaders, pair); - scheduleAll(m_plugInStreamLoaders, pair); - scheduleAll(m_multipartSubresourceLoaders, pair); -#endif -} - -void DocumentLoader::unschedule(SchedulePair* pair) -{ -#ifndef BUILDING_ON_TIGER - if (m_mainResourceLoader && m_mainResourceLoader->handle()) - m_mainResourceLoader->handle()->unschedule(pair); - unscheduleAll(m_subresourceLoaders, pair); - unscheduleAll(m_plugInStreamLoaders, pair); - unscheduleAll(m_multipartSubresourceLoaders, pair); -#endif -} - -} // namespace diff --git a/WebCore/loader/mac/LoaderNSURLExtras.h b/WebCore/loader/mac/LoaderNSURLExtras.h deleted file mode 100644 index ce5a490..0000000 --- a/WebCore/loader/mac/LoaderNSURLExtras.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import <Foundation/Foundation.h> - -#ifdef __cplusplus -extern "C" { -#endif - -NSString *suggestedFilenameWithMIMEType(NSURL *url, NSString *MIMEType); - -#ifdef __cplusplus -} -#endif diff --git a/WebCore/loader/mac/LoaderNSURLExtras.mm b/WebCore/loader/mac/LoaderNSURLExtras.mm deleted file mode 100644 index 9a507f5..0000000 --- a/WebCore/loader/mac/LoaderNSURLExtras.mm +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2005, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "config.h" -#import "LoaderNSURLExtras.h" - -#import <wtf/Assertions.h> -#import <wtf/Vector.h> -#import "KURL.h" -#import "LocalizedStrings.h" -#import "MIMETypeRegistry.h" -#import "PlatformString.h" -#import "WebCoreNSStringExtras.h" - -using namespace WebCore; - -static bool vectorContainsString(const Vector<String>& vector, const String& string) -{ - int size = vector.size(); - for (int i = 0; i < size; i++) - if (vector[i] == string) - return true; - return false; -} - -NSString *suggestedFilenameWithMIMEType(NSURL *url, NSString *MIMEType) -{ - // Get the filename from the URL. Try the lastPathComponent first. - NSString *lastPathComponent = [[url path] lastPathComponent]; - NSString *filename = filenameByFixingIllegalCharacters(lastPathComponent); - NSString *extension = nil; - - if ([filename length] == 0 || [lastPathComponent isEqualToString:@"/"]) { - // lastPathComponent is no good, try the host. - NSString *host = KURL(url).host(); - filename = filenameByFixingIllegalCharacters(host); - if ([filename length] == 0) { - // Can't make a filename using this URL, use "unknown". - filename = copyImageUnknownFileLabel(); - } - } else { - // Save the extension for later correction. Only correct the extension of the lastPathComponent. - // For example, if the filename ends up being the host, we wouldn't want to correct ".com" in "www.apple.com". - extension = [filename pathExtension]; - } - - // No mime type reported. Just return the filename we have now. - if (!MIMEType) { - return filename; - } - - // Do not correct filenames that are reported with a mime type of tar, and - // have a filename which has .tar in it or ends in .tgz - if (([MIMEType isEqualToString:@"application/tar"] || [MIMEType isEqualToString:@"application/x-tar"]) - && (hasCaseInsensitiveSubstring(filename, @".tar") - || hasCaseInsensitiveSuffix(filename, @".tgz"))) { - return filename; - } - - // I don't think we need to worry about this for the image case - // If the type is known, check the extension and correct it if necessary. - if (![MIMEType isEqualToString:@"application/octet-stream"] && ![MIMEType isEqualToString:@"text/plain"]) { - Vector<String> extensions = MIMETypeRegistry::getExtensionsForMIMEType(MIMEType); - - if (extensions.isEmpty() || !vectorContainsString(extensions, extension)) { - // The extension doesn't match the MIME type. Correct this. - NSString *correctExtension = MIMETypeRegistry::getPreferredExtensionForMIMEType(MIMEType); - if ([correctExtension length] != 0) { - // Append the correct extension. - filename = [filename stringByAppendingPathExtension:correctExtension]; - } - } - } - - return filename; -} diff --git a/WebCore/loader/mac/ResourceLoaderMac.mm b/WebCore/loader/mac/ResourceLoaderMac.mm deleted file mode 100644 index 9769ac9..0000000 --- a/WebCore/loader/mac/ResourceLoaderMac.mm +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "ResourceLoader.h" - -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "ResourceHandle.h" - -namespace WebCore { - -NSCachedURLResponse* ResourceLoader::willCacheResponse(ResourceHandle* handle, NSCachedURLResponse* response) -{ - return frameLoader()->client()->willCacheResponse(documentLoader(), identifier(), response); -} - -} diff --git a/WebCore/loader/win/DocumentLoaderWin.cpp b/WebCore/loader/win/DocumentLoaderWin.cpp deleted file mode 100644 index bab7de6..0000000 --- a/WebCore/loader/win/DocumentLoaderWin.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2006 Don Gibson <dgibson77@gmail.com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DocumentLoader.h" - -#include "FrameWin.h" -#include "PlatformString.h" - -namespace WebCore { - -void DocumentLoader::setTitle(const String& title) -{ - String text = title; - text.replace('//', m_frame->backslashAsCurrencySymbol()); - - FrameWin* frameWin = static_cast<FrameWin*>(m_frame); - if (frameWin->client()) - frameWin->client()->setTitle(text); -} - -} diff --git a/WebCore/loader/win/FrameLoaderWin.cpp b/WebCore/loader/win/FrameLoaderWin.cpp deleted file mode 100644 index 66aa6ff..0000000 --- a/WebCore/loader/win/FrameLoaderWin.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2006 Don Gibson <dgibson77@gmail.com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FrameLoader.h" - -#include "DocumentLoader.h" -#include "FrameLoadRequest.h" -#include "FrameWin.h" -#include "ResourceRequest.h" - -namespace WebCore { - -void FrameLoader::urlSelected(const FrameLoadRequest& request, Event* /*triggering Event*/) -{ - FrameWin* frameWin = static_cast<FrameWin*>(m_frame); - if (frameWin->client()) - frameWin->client()->openURL(request.resourceRequest().url().string(), request.lockHistory()); -} - -void FrameLoader::submitForm(const FrameLoadRequest& request, Event*) -{ - const ResourceRequest& resourceRequest = request.resourceRequest(); - -#ifdef MULTIPLE_FORM_SUBMISSION_PROTECTION - // FIXME: this is a hack inherited from FrameMac, and should be pushed into Frame - if (m_submittedFormURL == resourceRequest.url()) - return; - m_submittedFormURL = resourceRequest.url(); -#endif - - FrameWin* frameWin = static_cast<FrameWin*>(m_frame); - if (frameWin->client()) - frameWin->client()->submitForm(resourceRequest.httpMethod(), resourceRequest.url(), resourceRequest.httpBody()); - - clearRecordedFormValues(); -} - -} |