diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/loader | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/loader')
139 files changed, 0 insertions, 32529 deletions
diff --git a/WebCore/loader/CachedMetadata.h b/WebCore/loader/CachedMetadata.h deleted file mode 100644 index 120e4c0..0000000 --- a/WebCore/loader/CachedMetadata.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 CachedMetadata_h -#define CachedMetadata_h - -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WebCore { - -// Metadata retrieved from the embedding application's cache. -// -// Serialized data is NOT portable across architectures. However, reading the -// data type ID will reject data generated with a different byte-order. -class CachedMetadata : public RefCounted<CachedMetadata> { -public: - static PassRefPtr<CachedMetadata> create(unsigned dataTypeID, const char* data, size_t size) - { - return adoptRef(new CachedMetadata(dataTypeID, data, size)); - } - - static PassRefPtr<CachedMetadata> deserialize(const char* data, size_t size) - { - return adoptRef(new CachedMetadata(data, size)); - } - - const Vector<char>& serialize() const - { - return m_serializedData; - } - - ~CachedMetadata() { } - - unsigned dataTypeID() const - { - return readUnsigned(dataTypeIDStart); - } - - const char* data() const - { - if (m_serializedData.size() < dataStart) - return 0; - return m_serializedData.data() + dataStart; - } - - size_t size() const - { - if (m_serializedData.size() < dataStart) - return 0; - return m_serializedData.size() - dataStart; - } - -private: - // Reads an unsigned value at position. Returns 0 on error. - unsigned readUnsigned(size_t position) const - { - if (m_serializedData.size() < position + sizeof(unsigned)) - return 0; - return *reinterpret_cast_ptr<unsigned*>(const_cast<char*>(m_serializedData.data() + position)); - } - - // Appends an unsigned value to the end of the serialized data. - void appendUnsigned(unsigned value) - { - m_serializedData.append(reinterpret_cast<const char*>(&value), sizeof(unsigned)); - } - - CachedMetadata(const char* data, size_t size) - { - // Serialized metadata should have non-empty data. - ASSERT(size > dataStart); - - m_serializedData.append(data, size); - } - - CachedMetadata(unsigned dataTypeID, const char* data, size_t size) - { - // Don't allow an ID of 0, it is used internally to indicate errors. - ASSERT(dataTypeID); - ASSERT(data); - - appendUnsigned(dataTypeID); - m_serializedData.append(data, size); - } - - // Serialization offsets. Format: [DATA_TYPE_ID][DATA]. - static const size_t dataTypeIDStart = 0; - static const size_t dataStart = sizeof(unsigned); - - // Since the serialization format supports random access, storing it in - // serialized form avoids need for a copy during serialization. - Vector<char> m_serializedData; -}; - -} - -#endif diff --git a/WebCore/loader/CrossOriginAccessControl.cpp b/WebCore/loader/CrossOriginAccessControl.cpp deleted file mode 100644 index 8ca821e..0000000 --- a/WebCore/loader/CrossOriginAccessControl.cpp +++ /dev/null @@ -1,128 +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 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 "CrossOriginAccessControl.h" - -#include "HTTPParsers.h" -#include "ResourceResponse.h" -#include "SecurityOrigin.h" -#include <wtf/HashSet.h> -#include <wtf/Threading.h> -#include <wtf/text/AtomicString.h> - -namespace WebCore { - -bool isOnAccessControlSimpleRequestMethodWhitelist(const String& method) -{ - return method == "GET" || method == "HEAD" || method == "POST"; -} - -bool isOnAccessControlSimpleRequestHeaderWhitelist(const String& name, const String& value) -{ - if (equalIgnoringCase(name, "accept") || equalIgnoringCase(name, "accept-language") || equalIgnoringCase(name, "content-language")) - return true; - - // Preflight is required for MIME types that can not be sent via form submission. - if (equalIgnoringCase(name, "content-type")) { - String mimeType = extractMIMETypeFromMediaType(value); - return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded") - || equalIgnoringCase(mimeType, "multipart/form-data") - || equalIgnoringCase(mimeType, "text/plain"); - } - - return false; -} - -bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap) -{ - if (!isOnAccessControlSimpleRequestMethodWhitelist(method)) - return false; - - HTTPHeaderMap::const_iterator end = headerMap.end(); - for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) { - if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->first, it->second)) - return false; - } - - return true; -} - -typedef HashSet<String, CaseFoldingHash> HTTPHeaderSet; -static PassOwnPtr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet() -{ - OwnPtr<HTTPHeaderSet> headerSet = adoptPtr(new HashSet<String, CaseFoldingHash>); - - headerSet->add("cache-control"); - headerSet->add("content-language"); - headerSet->add("content-type"); - headerSet->add("expires"); - headerSet->add("last-modified"); - headerSet->add("pragma"); - - return headerSet.release(); -} - -bool isOnAccessControlResponseHeaderWhitelist(const String& name) -{ - AtomicallyInitializedStatic(HTTPHeaderSet*, allowedCrossOriginResponseHeaders = createAllowedCrossOriginResponseHeadersSet().leakPtr()); - - return allowedCrossOriginResponseHeaders->contains(name); -} - -bool passesAccessControlCheck(const ResourceResponse& response, bool includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription) -{ - // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent, - // even with Access-Control-Allow-Credentials set to true. - const String& accessControlOriginString = response.httpHeaderField("Access-Control-Allow-Origin"); - if (accessControlOriginString == "*" && !includeCredentials) - return true; - - if (securityOrigin->isUnique()) { - errorDescription = "Cannot make any requests from " + securityOrigin->toString() + "."; - return false; - } - - // FIXME: Access-Control-Allow-Origin can contain a list of origins. - RefPtr<SecurityOrigin> accessControlOrigin = SecurityOrigin::createFromString(accessControlOriginString); - if (!accessControlOrigin->isSameSchemeHostPort(securityOrigin)) { - errorDescription = (accessControlOriginString == "*") ? "Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true." - : "Origin " + securityOrigin->toString() + " is not allowed by Access-Control-Allow-Origin."; - return false; - } - - if (includeCredentials) { - const String& accessControlCredentialsString = response.httpHeaderField("Access-Control-Allow-Credentials"); - if (accessControlCredentialsString != "true") { - errorDescription = "Credentials flag is true, but Access-Control-Allow-Credentials is not \"true\"."; - return false; - } - } - - return true; -} - -} // namespace WebCore diff --git a/WebCore/loader/CrossOriginAccessControl.h b/WebCore/loader/CrossOriginAccessControl.h deleted file mode 100644 index c44963b..0000000 --- a/WebCore/loader/CrossOriginAccessControl.h +++ /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 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 <wtf/Forward.h> - -namespace WebCore { - - class HTTPHeaderMap; - class ResourceResponse; - class SecurityOrigin; - - bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&); - bool isOnAccessControlSimpleRequestMethodWhitelist(const String&); - bool isOnAccessControlSimpleRequestHeaderWhitelist(const String& name, const String& value); - bool isOnAccessControlResponseHeaderWhitelist(const String&); - - bool passesAccessControlCheck(const ResourceResponse&, bool includeCredentials, SecurityOrigin*, String& errorDescription); - -} // namespace WebCore diff --git a/WebCore/loader/CrossOriginPreflightResultCache.cpp b/WebCore/loader/CrossOriginPreflightResultCache.cpp deleted file mode 100644 index 18e4be2..0000000 --- a/WebCore/loader/CrossOriginPreflightResultCache.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "CrossOriginPreflightResultCache.h" - -#include "CrossOriginAccessControl.h" -#include "ResourceResponse.h" -#include <wtf/CurrentTime.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Threading.h> - -namespace WebCore { - -using namespace std; - -// These values are at the discretion of the user agent. -static const unsigned defaultPreflightCacheTimeoutSeconds = 5; -static const unsigned maxPreflightCacheTimeoutSeconds = 600; // Should be short enough to minimize the risk of using a poisoned cache after switching to a secure network. - -static bool parseAccessControlMaxAge(const String& string, unsigned& expiryDelta) -{ - // FIXME: this will not do the correct thing for a number starting with a '+' - bool ok = false; - expiryDelta = string.toUIntStrict(&ok); - return ok; -} - -template<class HashType> -static void addToAccessControlAllowList(const String& string, unsigned start, unsigned end, HashSet<String, HashType>& set) -{ - StringImpl* stringImpl = string.impl(); - if (!stringImpl) - return; - - // Skip white space from start. - while (start <= end && isSpaceOrNewline((*stringImpl)[start])) - ++start; - - // only white space - if (start > end) - return; - - // Skip white space from end. - while (end && isSpaceOrNewline((*stringImpl)[end])) - --end; - - set.add(string.substring(start, end - start + 1)); -} - -template<class HashType> -static bool parseAccessControlAllowList(const String& string, HashSet<String, HashType>& set) -{ - unsigned start = 0; - size_t end; - while ((end = string.find(',', start)) != notFound) { - if (start == end) - return false; - - addToAccessControlAllowList(string, start, end - 1, set); - start = end + 1; - } - if (start != string.length()) - addToAccessControlAllowList(string, start, string.length() - 1, set); - - return true; -} - -bool CrossOriginPreflightResultCacheItem::parse(const ResourceResponse& response, String& errorDescription) -{ - m_methods.clear(); - if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Methods"), m_methods)) { - errorDescription = "Cannot parse Access-Control-Allow-Methods response header field."; - return false; - } - - m_headers.clear(); - if (!parseAccessControlAllowList(response.httpHeaderField("Access-Control-Allow-Headers"), m_headers)) { - errorDescription = "Cannot parse Access-Control-Allow-Headers response header field."; - return false; - } - - unsigned expiryDelta; - if (parseAccessControlMaxAge(response.httpHeaderField("Access-Control-Max-Age"), expiryDelta)) { - if (expiryDelta > maxPreflightCacheTimeoutSeconds) - expiryDelta = maxPreflightCacheTimeoutSeconds; - } else - expiryDelta = defaultPreflightCacheTimeoutSeconds; - - m_absoluteExpiryTime = currentTime() + expiryDelta; - return true; -} - -bool CrossOriginPreflightResultCacheItem::allowsCrossOriginMethod(const String& method, String& errorDescription) const -{ - if (m_methods.contains(method) || isOnAccessControlSimpleRequestMethodWhitelist(method)) - return true; - - errorDescription = "Method " + method + " is not allowed by Access-Control-Allow-Methods."; - return false; -} - -bool CrossOriginPreflightResultCacheItem::allowsCrossOriginHeaders(const HTTPHeaderMap& requestHeaders, String& errorDescription) const -{ - HTTPHeaderMap::const_iterator end = requestHeaders.end(); - for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) { - if (!m_headers.contains(it->first) && !isOnAccessControlSimpleRequestHeaderWhitelist(it->first, it->second)) { - errorDescription = "Request header field " + it->first.string() + " is not allowed by Access-Control-Allow-Headers."; - return false; - } - } - return true; -} - -bool CrossOriginPreflightResultCacheItem::allowsRequest(bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders) const -{ - String ignoredExplanation; - if (m_absoluteExpiryTime < currentTime()) - return false; - if (includeCredentials && !m_credentials) - return false; - if (!allowsCrossOriginMethod(method, ignoredExplanation)) - return false; - if (!allowsCrossOriginHeaders(requestHeaders, ignoredExplanation)) - return false; - return true; -} - -CrossOriginPreflightResultCache& CrossOriginPreflightResultCache::shared() -{ - DEFINE_STATIC_LOCAL(CrossOriginPreflightResultCache, cache, ()); - ASSERT(isMainThread()); - return cache; -} - -void CrossOriginPreflightResultCache::appendEntry(const String& origin, const KURL& url, PassOwnPtr<CrossOriginPreflightResultCacheItem> preflightResult) -{ - ASSERT(isMainThread()); - CrossOriginPreflightResultCacheItem* resultPtr = preflightResult.leakPtr(); - pair<CrossOriginPreflightResultHashMap::iterator, bool> addResult = m_preflightHashMap.add(make_pair(origin, url), resultPtr); - if (!addResult.second) { - // FIXME: We need to delete the old value before replacing with the new one. - addResult.first->second = resultPtr; - } -} - -bool CrossOriginPreflightResultCache::canSkipPreflight(const String& origin, const KURL& url, bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders) -{ - ASSERT(isMainThread()); - CrossOriginPreflightResultHashMap::iterator cacheIt = m_preflightHashMap.find(std::make_pair(origin, url)); - if (cacheIt == m_preflightHashMap.end()) - return false; - - if (cacheIt->second->allowsRequest(includeCredentials, method, requestHeaders)) - return true; - - delete cacheIt->second; - m_preflightHashMap.remove(cacheIt); - return false; -} - -void CrossOriginPreflightResultCache::empty() -{ - ASSERT(isMainThread()); - deleteAllValues(m_preflightHashMap); - m_preflightHashMap.clear(); -} - -} // namespace WebCore diff --git a/WebCore/loader/CrossOriginPreflightResultCache.h b/WebCore/loader/CrossOriginPreflightResultCache.h deleted file mode 100644 index 1016aed..0000000 --- a/WebCore/loader/CrossOriginPreflightResultCache.h +++ /dev/null @@ -1,85 +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 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 CrossOriginPreflightResultCache_h -#define CrossOriginPreflightResultCache_h - -#include "KURLHash.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - - class HTTPHeaderMap; - class ResourceResponse; - - class CrossOriginPreflightResultCacheItem : public Noncopyable { - public: - CrossOriginPreflightResultCacheItem(bool credentials) - : m_absoluteExpiryTime(0) - , m_credentials(credentials) - { - } - - bool parse(const ResourceResponse&, String& errorDescription); - bool allowsCrossOriginMethod(const String&, String& errorDescription) const; - bool allowsCrossOriginHeaders(const HTTPHeaderMap&, String& errorDescription) const; - bool allowsRequest(bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders) const; - - private: - typedef HashSet<String, CaseFoldingHash> HeadersSet; - - // FIXME: A better solution to holding onto the absolute expiration time might be - // to start a timer for the expiration delta that removes this from the cache when - // it fires. - double m_absoluteExpiryTime; - bool m_credentials; - HashSet<String> m_methods; - HeadersSet m_headers; - }; - - class CrossOriginPreflightResultCache : public Noncopyable { - public: - static CrossOriginPreflightResultCache& shared(); - - void appendEntry(const String& origin, const KURL&, PassOwnPtr<CrossOriginPreflightResultCacheItem>); - bool canSkipPreflight(const String& origin, const KURL&, bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders); - - void empty(); - - private: - CrossOriginPreflightResultCache() { } - - typedef HashMap<std::pair<String, KURL>, CrossOriginPreflightResultCacheItem*> CrossOriginPreflightResultHashMap; - - CrossOriginPreflightResultHashMap m_preflightHashMap; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/loader/DocumentLoadTiming.h b/WebCore/loader/DocumentLoadTiming.h deleted file mode 100644 index 368004b..0000000 --- a/WebCore/loader/DocumentLoadTiming.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 Google, 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 GOOGLE 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 GOOGLE 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 DocumentLoadTiming_h -#define DocumentLoadTiming_h - -namespace WebCore { - -struct DocumentLoadTiming { - DocumentLoadTiming() - : navigationStart(0.0) - , unloadEventStart(0.0) - , unloadEventEnd(0.0) - , redirectStart(0.0) - , redirectEnd(0.0) - , redirectCount(0) - , fetchStart(0.0) - , responseEnd(0.0) - , loadEventStart(0.0) - , loadEventEnd(0.0) - { - } - - double navigationStart; - double unloadEventStart; - double unloadEventEnd; - double redirectStart; - double redirectEnd; - short redirectCount; - double fetchStart; - double responseEnd; - double loadEventStart; - double loadEventEnd; -}; - -} - -#endif diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp deleted file mode 100644 index 4e7c656..0000000 --- a/WebCore/loader/DocumentLoader.cpp +++ /dev/null @@ -1,840 +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" - -#include "ApplicationCacheHost.h" -#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 "CachedResourceLoader.h" -#include "DOMWindow.h" -#include "Document.h" -#include "DocumentParser.h" -#include "Event.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.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 <wtf/Assertions.h> -#include <wtf/text/CString.h> -#include <wtf/unicode/Unicode.h> - -namespace WebCore { - -static void cancelAll(const ResourceLoaderSet& loaders) -{ - Vector<RefPtr<ResourceLoader> > loadersCopy; - copyToVector(loaders, loadersCopy); - size_t size = loadersCopy.size(); - for (size_t i = 0; i < size; ++i) - loadersCopy[i]->cancel(); -} - -static void setAllDefersLoading(const ResourceLoaderSet& loaders, bool defers) -{ - Vector<RefPtr<ResourceLoader> > loadersCopy; - copyToVector(loaders, loadersCopy); - size_t size = loadersCopy.size(); - for (size_t i = 0; i < size; ++i) - loadersCopy[i]->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_wasOnloadHandled(false) - , m_stopRecordingResponses(false) - , m_substituteResourceDeliveryTimer(this, &DocumentLoader::substituteResourceDeliveryTimerFired) - , m_didCreateGlobalHistoryEntry(false) -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - , m_applicationCacheHost(adoptPtr(new ApplicationCacheHost(this))) -#endif -{ -} - -FrameLoader* DocumentLoader::frameLoader() const -{ - if (!m_frame) - return 0; - return m_frame->loader(); -} - -DocumentLoader::~DocumentLoader() -{ - ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !frameLoader()->isLoading()); -} - -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::replaceRequestURLForSameDocumentNavigation(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) -{ - ASSERT(!error.isNull()); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - m_applicationCacheHost->failedLoadingMainResource(); -#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(DatabasePolicy databasePolicy) -{ - // 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->parsing()) - m_frame->loader()->stopLoading(UnloadEventPolicyNone, databasePolicy); - } - - // Always cancel multipart loaders - cancelAll(m_multipartSubresourceLoaders); - - // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads. -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - m_applicationCacheHost->stopLoadingInFrame(m_frame); -#endif - - 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(); - } -} - -void DocumentLoader::finishedLoading() -{ - m_gotFirstByte = true; - commitIfReady(); - if (FrameLoader* loader = frameLoader()) { - loader->finishedLoadingDocument(this); - loader->writer()->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(); - FrameLoader* frameLoader = DocumentLoader::frameLoader(); - if (!frameLoader) - return; -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (ArchiveFactory::isArchiveMimeType(response().mimeType())) - return; -#endif - frameLoader->client()->committedLoad(this, data, length); -} - -void DocumentLoader::commitData(const char* bytes, int length) -{ - // Set the text encoding. This is safe to call multiple times. - bool userChosen = true; - String encoding = overrideEncoding(); - if (encoding.isNull()) { - userChosen = false; - encoding = response().textEncodingName(); - } - // FIXME: DocumentWriter should be owned by DocumentLoader. - m_frame->loader()->writer()->setEncoding(encoding, userChosen); - ASSERT(m_frame->document()->parsing()); - m_frame->loader()->writer()->addData(bytes, 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()->writer()->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() -{ - if (!m_frame) { - setLoading(false); - return; - } - ASSERT(this == frameLoader()->activeDocumentLoader()); - bool wasLoading = m_loading; - setLoading(frameLoader()->isLoading()); - - if (wasLoading && !m_loading) { - if (DOMWindow* window = m_frame->existingDOMWindow()) - window->finishedLoading(); - } -} - -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); -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - m_applicationCacheHost->setDOMApplicationCache(0); -#endif - 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(); - m_mainResourceLoader = 0; - } - - if (this == frameLoader()->activeDocumentLoader()) - 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; - Document* doc = m_frame->document(); - if (doc->cachedResourceLoader()->requestCount()) - return true; - if (DocumentParser* parser = doc->parser()) - if (parser->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 = adoptPtr(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 = adoptPtr(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()->uniqueName()); -} - -PassRefPtr<ArchiveResource> DocumentLoader::subresource(const KURL& url) const -{ - if (!isCommitted()) - return 0; - - CachedResource* resource = m_frame->document()->cachedResourceLoader()->cachedResource(url); - if (!resource || !resource->isLoaded()) - return archiveResourceForURL(url); - - // FIXME: This has the side effect of making the resource non-purgeable. - // It would be better if it didn't have this permanent effect. - if (!resource->makePurgeable(false)) - return 0; - - RefPtr<SharedBuffer> data = resource->data(); - if (!data) - return 0; - - return ArchiveResource::create(data.release(), url, resource->response()); -} - -void DocumentLoader::getSubresources(Vector<PassRefPtr<ArchiveResource> >& subresources) const -{ - if (!isCommitted()) - return; - - Document* document = m_frame->document(); - - const CachedResourceLoader::DocumentResourceMap& allResources = document->cachedResourceLoader()->allCachedResources(); - CachedResourceLoader::DocumentResourceMap::const_iterator end = allResources.end(); - for (CachedResourceLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) { - RefPtr<ArchiveResource> subresource = this->subresource(KURL(ParsedURLString, 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(0); - } 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; - - if (m_pageTitle != title) { - frameLoader()->willChangeTitle(this); - m_pageTitle = title; - frameLoader()->didChangeTitle(this); - } -} - -void DocumentLoader::setIconURL(const String& iconURL) -{ - if (iconURL.isEmpty()) - return; - - if (m_pageIconURL != iconURL) { - m_pageIconURL = iconURL; - frameLoader()->didChangeIcons(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(); -} - -bool DocumentLoader::urlForHistoryReflectsFailure() const -{ - return m_substituteData.isValid() || m_response.httpStatusCode() >= 400; -} - -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()->addExtraFieldsToMainResourceRequest(m_request); - - 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::transferLoadingResourcesFromPage(Page* oldPage) -{ - ASSERT(oldPage != m_frame->page()); - - FrameLoader* loader = frameLoader(); - ASSERT(loader); - - const ResourceRequest& request = originalRequest(); - if (isLoadingMainResource()) { - loader->dispatchTransferLoadingResourceFromPage( - m_mainResourceLoader->identifier(), this, request, oldPage); - } - - if (isLoadingSubresources()) { - ResourceLoaderSet::const_iterator it = m_subresourceLoaders.begin(); - ResourceLoaderSet::const_iterator end = m_subresourceLoaders.end(); - for (; it != end; ++it) { - loader->dispatchTransferLoadingResourceFromPage( - (*it)->identifier(), this, request, oldPage); - } - } -} - -void DocumentLoader::iconLoadDecisionAvailable() -{ - if (m_frame) - m_frame->loader()->iconLoadDecisionAvailable(); -} - -} diff --git a/WebCore/loader/DocumentLoader.h b/WebCore/loader/DocumentLoader.h deleted file mode 100644 index 2328160..0000000 --- a/WebCore/loader/DocumentLoader.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 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 "DocumentLoadTiming.h" -#include "NavigationAction.h" -#include "ResourceError.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "SubstituteData.h" -#include "Timer.h" - -namespace WebCore { - - class ApplicationCacheHost; -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - class Archive; - class ArchiveResource; - class ArchiveResourceCollection; -#endif - class Frame; - class FrameLoader; - class MainResourceLoader; - class Page; - class ResourceLoader; - class SchedulePair; - class SharedBuffer; - 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 replaceRequestURLForSameDocumentNavigation(const KURL&); - bool isStopping() const { return m_isStopping; } - void stopLoading(DatabasePolicy = DatabasePolicyStop); - 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; } - void handledOnloadEvents() { m_wasOnloadHandled = true; } - bool wasOnloadHandled() { return m_wasOnloadHandled; } - bool isLoadingInAPISense() const; - void setPrimaryLoadComplete(bool); - void setTitle(const String&); - void setIconURL(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; } - const String& iconURL() const { return m_pageIconURL; } - - KURL urlForHistory() const; - bool urlForHistoryReflectsFailure() const; - - // These accessors accommodate WebCore's somewhat fickle custom of creating history - // items for redirects, but only sometimes. For "source" and "destination", - // these accessors return the URL that would have been used if a history - // item were created. This allows WebKit to link history items reflecting - // redirects into a chain from start to finish. - String clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; } // null if no client redirect occurred. - String clientRedirectDestinationForHistory() const { return urlForHistory(); } - void setClientRedirectSourceForHistory(const String& clientedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientedirectSourceForHistory; } - - String serverRedirectSourceForHistory() const { return urlForHistory() == url() ? String() : urlForHistory(); } // null if no server redirect occurred. - String serverRedirectDestinationForHistory() const { return url(); } - - bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; } - void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; } - - 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 transferLoadingResourcesFromPage(Page*); - - void setDeferMainResourceDataLoad(bool defer) { m_deferMainResourceDataLoad = defer; } - bool deferMainResourceDataLoad() const { return m_deferMainResourceDataLoad; } - - void didTellClientAboutLoad(const String& url) - { - if (!url.isEmpty()) - m_resourcesClientKnowsAbout.add(url); - } - bool haveToldClientAboutLoad(const String& url) { return m_resourcesClientKnowsAbout.contains(url); } - void recordMemoryCacheLoadForFutureClientNotification(const String& url); - void takeMemoryCacheLoadsForClientNotification(Vector<String>& loads); - - DocumentLoadTiming* timing() { return &m_documentLoadTiming; } - void resetTiming() { m_documentLoadTiming = DocumentLoadTiming(); } - - // The WebKit layer calls this function when it's ready for the data to - // actually be added to the document. - void commitData(const char* bytes, int length); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); } -#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_wasOnloadHandled; - - String m_pageTitle; - String m_pageIconURL; - - 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 - - HashSet<String> m_resourcesClientKnowsAbout; - Vector<String> m_resourcesLoadedFromMemoryCacheForClientNotification; - - String m_clientRedirectSourceForHistory; - bool m_didCreateGlobalHistoryEntry; - - DocumentLoadTiming m_documentLoadTiming; - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - friend class ApplicationCacheHost; // for substitute resource delivery - OwnPtr<ApplicationCacheHost> m_applicationCacheHost; -#endif - }; - - inline void DocumentLoader::recordMemoryCacheLoadForFutureClientNotification(const String& url) - { - m_resourcesLoadedFromMemoryCacheForClientNotification.append(url); - } - - inline void DocumentLoader::takeMemoryCacheLoadsForClientNotification(Vector<String>& loadsSet) - { - loadsSet.swap(m_resourcesLoadedFromMemoryCacheForClientNotification); - m_resourcesLoadedFromMemoryCacheForClientNotification.clear(); - } - -} - -#endif // DocumentLoader_h diff --git a/WebCore/loader/DocumentThreadableLoader.cpp b/WebCore/loader/DocumentThreadableLoader.cpp deleted file mode 100644 index dee5001..0000000 --- a/WebCore/loader/DocumentThreadableLoader.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "DocumentThreadableLoader.h" - -#include "AuthenticationChallenge.h" -#include "CrossOriginAccessControl.h" -#include "CrossOriginPreflightResultCache.h" -#include "Document.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "ResourceHandle.h" -#include "ResourceLoadScheduler.h" -#include "ResourceRequest.h" -#include "SecurityOrigin.h" -#include "SubresourceLoader.h" -#include "ThreadableLoaderClient.h" -#include <wtf/UnusedParam.h> - -namespace WebCore { - -void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) -{ - // The loader will be deleted as soon as this function exits. - RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options)); - ASSERT(loader->hasOneRef()); -} - -PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options) -{ - RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options)); - if (!loader->m_loader) - loader = 0; - return loader.release(); -} - -DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) - : m_client(client) - , m_document(document) - , m_options(options) - , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url())) - , m_async(blockingBehavior == LoadAsynchronously) -{ - ASSERT(document); - ASSERT(client); - - if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { - loadRequest(request, DoSecurityCheck); - return; - } - - if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { - m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are not supported.")); - return; - } - - ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); - - OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceRequest(request)); - crossOriginRequest->removeCredentials(); - crossOriginRequest->setAllowCookies(m_options.allowCredentials); - - if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) - makeSimpleCrossOriginAccessRequest(*crossOriginRequest); - else { - m_actualRequest = crossOriginRequest.release(); - - if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) - preflightSuccess(); - else - makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); - } -} - -void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request) -{ - ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())); - - // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied. - if (!request.url().protocolInHTTPFamily()) { - m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are only supported for HTTP.")); - return; - } - - // Make a copy of the passed request so that we can modify some details. - ResourceRequest crossOriginRequest(request); - crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); - - loadRequest(crossOriginRequest, DoSecurityCheck); -} - -void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request) -{ - ResourceRequest preflightRequest(request.url()); - preflightRequest.removeCredentials(); - preflightRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); - preflightRequest.setAllowCookies(m_options.allowCredentials); - preflightRequest.setHTTPMethod("OPTIONS"); - preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod()); - - const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields(); - - if (requestHeaderFields.size() > 0) { - Vector<UChar> headerBuffer; - HTTPHeaderMap::const_iterator it = requestHeaderFields.begin(); - append(headerBuffer, it->first); - ++it; - - HTTPHeaderMap::const_iterator end = requestHeaderFields.end(); - for (; it != end; ++it) { - headerBuffer.append(','); - headerBuffer.append(' '); - append(headerBuffer, it->first); - } - - preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer)); - } - - loadRequest(preflightRequest, DoSecurityCheck); -} - -DocumentThreadableLoader::~DocumentThreadableLoader() -{ - if (m_loader) - m_loader->clearClient(); -} - -void DocumentThreadableLoader::cancel() -{ - if (!m_loader) - return; - - m_loader->cancel(); - m_loader->clearClient(); - m_loader = 0; - m_client = 0; -} - -void DocumentThreadableLoader::willSendRequest(SubresourceLoader* loader, ResourceRequest& request, const ResourceResponse&) -{ - ASSERT(m_client); - ASSERT_UNUSED(loader, loader == m_loader); - - if (!isAllowedRedirect(request.url())) { - RefPtr<DocumentThreadableLoader> protect(this); - m_client->didFailRedirectCheck(); - request = ResourceRequest(); - } -} - -void DocumentThreadableLoader::didSendData(SubresourceLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - ASSERT(m_client); - ASSERT_UNUSED(loader, loader == m_loader); - - m_client->didSendData(bytesSent, totalBytesToBeSent); -} - -void DocumentThreadableLoader::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response) -{ - ASSERT(m_client); - ASSERT_UNUSED(loader, loader == m_loader); - - String accessControlErrorDescription; - if (m_actualRequest) { - if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin(), accessControlErrorDescription)) { - preflightFailure(response.url(), accessControlErrorDescription); - return; - } - - OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new CrossOriginPreflightResultCacheItem(m_options.allowCredentials)); - if (!preflightResult->parse(response, accessControlErrorDescription) - || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod(), accessControlErrorDescription) - || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeaderFields(), accessControlErrorDescription)) { - preflightFailure(response.url(), accessControlErrorDescription); - return; - } - - CrossOriginPreflightResultCache::shared().appendEntry(m_document->securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release()); - } else { - if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) { - if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin(), accessControlErrorDescription)) { - m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, response.url().string(), accessControlErrorDescription)); - return; - } - } - - m_client->didReceiveResponse(response); - } -} - -void DocumentThreadableLoader::didReceiveData(SubresourceLoader* loader, const char* data, int lengthReceived) -{ - ASSERT(m_client); - ASSERT_UNUSED(loader, loader == m_loader); - - // Ignore response body of preflight requests. - if (m_actualRequest) - return; - - m_client->didReceiveData(data, lengthReceived); -} - -void DocumentThreadableLoader::didFinishLoading(SubresourceLoader* loader) -{ - ASSERT(loader == m_loader); - ASSERT(m_client); - didFinishLoading(loader->identifier()); -} - -void DocumentThreadableLoader::didFinishLoading(unsigned long identifier) -{ - if (m_actualRequest) { - ASSERT(!m_sameOriginRequest); - ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); - preflightSuccess(); - } else - m_client->didFinishLoading(identifier); -} - -void DocumentThreadableLoader::didFail(SubresourceLoader* loader, const ResourceError& error) -{ - ASSERT(m_client); - // m_loader may be null if we arrive here via SubresourceLoader::create in the ctor - ASSERT_UNUSED(loader, loader == m_loader || !m_loader); - - m_client->didFail(error); -} - -bool DocumentThreadableLoader::getShouldUseCredentialStorage(SubresourceLoader* loader, bool& shouldUseCredentialStorage) -{ - ASSERT_UNUSED(loader, loader == m_loader || !m_loader); - - if (!m_options.allowCredentials) { - shouldUseCredentialStorage = false; - return true; - } - - return false; // Only FrameLoaderClient can ultimately permit credential use. -} - -void DocumentThreadableLoader::didReceiveAuthenticationChallenge(SubresourceLoader* loader, const AuthenticationChallenge& challenge) -{ - ASSERT(loader == m_loader); - // Users are not prompted for credentials for cross-origin requests. - if (!m_sameOriginRequest) { -#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL) - loader->handle()->receivedRequestToContinueWithoutCredential(challenge); -#else - // These platforms don't provide a way to continue without credentials, cancel the load altogether. - UNUSED_PARAM(challenge); - RefPtr<DocumentThreadableLoader> protect(this); - m_client->didFail(loader->blockedError()); - cancel(); -#endif - } -} - -void DocumentThreadableLoader::receivedCancellation(SubresourceLoader* loader, const AuthenticationChallenge& challenge) -{ - ASSERT(m_client); - ASSERT_UNUSED(loader, loader == m_loader); - m_client->didReceiveAuthenticationCancellation(challenge.failureResponse()); -} - -void DocumentThreadableLoader::preflightSuccess() -{ - OwnPtr<ResourceRequest> actualRequest; - actualRequest.swap(m_actualRequest); - - // It should be ok to skip the security check since we already asked about the preflight request. - loadRequest(*actualRequest, SkipSecurityCheck); -} - -void DocumentThreadableLoader::preflightFailure(const String& url, const String& errorDescription) -{ - m_actualRequest = 0; // Prevent didFinishLoading() from bypassing access check. - m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, url, errorDescription)); -} - -void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck) -{ - // Any credential should have been removed from the cross-site requests. - const KURL& requestURL = request.url(); - ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); - ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); - - if (m_async) { - // Don't sniff content or send load callbacks for the preflight request. - bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest; - bool sniffContent = m_options.sniffContent && !m_actualRequest; - - // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader. - m_loader = 0; - m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, securityCheck, sendLoadCallbacks, sniffContent); - return; - } - - // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests. - StoredCredentials storedCredentials = m_options.allowCredentials ? AllowStoredCredentials : DoNotAllowStoredCredentials; - - Vector<char> data; - ResourceError error; - ResourceResponse response; - unsigned long identifier = std::numeric_limits<unsigned long>::max(); - if (m_document->frame()) - identifier = m_document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data); - - // No exception for file:/// resources, see <rdar://problem/4962298>. - // Also, if we have an HTTP response, then it wasn't a network error in fact. - if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) { - m_client->didFail(error); - return; - } - - // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the - // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was - // requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials. - if (requestURL != response.url() && !isAllowedRedirect(response.url())) { - m_client->didFailRedirectCheck(); - return; - } - - didReceiveResponse(0, response); - - const char* bytes = static_cast<const char*>(data.data()); - int len = static_cast<int>(data.size()); - didReceiveData(0, bytes, len); - - didFinishLoading(identifier); -} - -bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) -{ - if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) - return true; - - // FIXME: We need to implement access control for each redirect. This will require some refactoring though, because the code - // that processes redirects doesn't know about access control and expects a synchronous answer from its client about whether - // a redirect should proceed. - return m_sameOriginRequest && m_document->securityOrigin()->canRequest(url); -} - -} // namespace WebCore diff --git a/WebCore/loader/DocumentThreadableLoader.h b/WebCore/loader/DocumentThreadableLoader.h deleted file mode 100644 index ebf3a25..0000000 --- a/WebCore/loader/DocumentThreadableLoader.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 DocumentThreadableLoader_h -#define DocumentThreadableLoader_h - -#include "FrameLoaderTypes.h" -#include "SubresourceLoaderClient.h" -#include "ThreadableLoader.h" -#include <wtf/Forward.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - class Document; - class KURL; - class ResourceRequest; - class ThreadableLoaderClient; - - class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient { - public: - static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&); - static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&); - virtual ~DocumentThreadableLoader(); - - virtual void cancel(); - - using RefCounted<DocumentThreadableLoader>::ref; - using RefCounted<DocumentThreadableLoader>::deref; - - protected: - virtual void refThreadableLoader() { ref(); } - virtual void derefThreadableLoader() { deref(); } - - private: - enum BlockingBehavior { - LoadSynchronously, - LoadAsynchronously - }; - - DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior blockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions& options); - - 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 lengthReceived); - virtual void didFinishLoading(SubresourceLoader*); - virtual void didFail(SubresourceLoader*, const ResourceError&); - - virtual bool getShouldUseCredentialStorage(SubresourceLoader*, bool& shouldUseCredentialStorage); - virtual void didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&); - virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&); - - void didFinishLoading(unsigned long identifier); - void makeSimpleCrossOriginAccessRequest(const ResourceRequest& request); - void makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request); - void preflightSuccess(); - void preflightFailure(const String& url, const String& errorDescription); - - void loadRequest(const ResourceRequest&, SecurityCheckPolicy); - bool isAllowedRedirect(const KURL&); - - RefPtr<SubresourceLoader> m_loader; - ThreadableLoaderClient* m_client; - Document* m_document; - ThreadableLoaderOptions m_options; - bool m_sameOriginRequest; - bool m_async; - OwnPtr<ResourceRequest> m_actualRequest; // non-null during Access Control preflight checks - }; - -} // namespace WebCore - -#endif // DocumentThreadableLoader_h diff --git a/WebCore/loader/DocumentWriter.cpp b/WebCore/loader/DocumentWriter.cpp deleted file mode 100644 index 5b03cd7..0000000 --- a/WebCore/loader/DocumentWriter.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2010. Adam Barth. 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 "DocumentWriter.h" - -#include "DOMImplementation.h" -#include "DOMWindow.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "FrameLoaderStateMachine.h" -#include "FrameView.h" -#include "PlaceholderDocument.h" -#include "PluginDocument.h" -#include "RawDataDocumentParser.h" -#include "ScriptableDocumentParser.h" -#include "SecurityOrigin.h" -#include "SegmentedString.h" -#include "Settings.h" -#include "SinkDocument.h" -#include "TextResourceDecoder.h" - - -namespace WebCore { - -static inline bool canReferToParentFrameEncoding(const Frame* frame, const Frame* parentFrame) -{ - return parentFrame && parentFrame->document()->securityOrigin()->canAccess(frame->document()->securityOrigin()); -} - -DocumentWriter::DocumentWriter(Frame* frame) - : m_frame(frame) - , m_receivedData(false) - , m_encodingWasChosenByUser(false) -{ -} - -// This is only called by ScriptController::executeIfJavaScriptURL -// and always contains the result of evaluating a javascript: url. -// This is the <iframe src="javascript:'html'"> case. -void DocumentWriter::replaceDocument(const String& source) -{ - m_frame->loader()->stopAllLoaders(); - begin(m_frame->loader()->url(), true, m_frame->document()->securityOrigin()); - - if (!source.isNull()) { - if (!m_receivedData) { - m_receivedData = true; - m_frame->document()->setCompatibilityMode(Document::NoQuirksMode); - } - - // FIXME: This should call DocumentParser::appendBytes instead of append - // to support RawDataDocumentParsers. - if (DocumentParser* parser = m_frame->document()->parser()) - parser->append(source); - } - - end(); -} - -void DocumentWriter::clear() -{ - m_decoder = 0; - m_receivedData = false; - if (!m_encodingWasChosenByUser) - m_encoding = String(); -} - -void DocumentWriter::begin() -{ - begin(KURL()); -} - -PassRefPtr<Document> DocumentWriter::createDocument(const KURL& url) -{ - if (!m_frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && m_frame->loader()->client()->shouldUsePluginDocument(m_mimeType)) - return PluginDocument::create(m_frame, url); - if (!m_frame->loader()->client()->hasHTMLView()) - return PlaceholderDocument::create(m_frame, url); - return DOMImplementation::createDocument(m_mimeType, m_frame, url, m_frame->inViewSourceMode()); -} - -void DocumentWriter::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; - - // Create a new document before clearing the frame, because it may need to - // inherit an aliased security context. - RefPtr<Document> document = createDocument(url); - - // If the new document is for a Plugin but we're supposed to be sandboxed from Plugins, - // then replace the document with one whose parser will ignore the incoming data (bug 39323) - if (document->isPluginDocument() && m_frame->loader()->isSandboxed(SandboxPlugins)) - document = SinkDocument::create(m_frame, url); - - bool resetScripting = !(m_frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && m_frame->document()->securityOrigin()->isSecureTransitionTo(url)); - m_frame->loader()->clear(resetScripting, resetScripting); - if (resetScripting) - m_frame->script()->updatePlatformScriptObjects(); - - m_frame->loader()->setURL(url); - m_frame->setDocument(document); - - 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()); - - m_frame->loader()->didBeginDocument(dispatch); - - document->implicitOpen(); - - if (m_frame->view() && m_frame->loader()->client()->hasHTMLView()) - m_frame->view()->setContentsSize(IntSize()); -} - -TextResourceDecoder* DocumentWriter::createDecoderIfNeeded() -{ - if (!m_decoder) { - if (Settings* settings = m_frame->settings()) { - m_decoder = TextResourceDecoder::create(m_mimeType, - settings->defaultTextEncodingName(), - settings->usesEncodingDetector()); - Frame* parentFrame = m_frame->tree()->parent(); - // Set the hint encoding to the parent frame encoding only if - // the parent and the current frames share the security origin. - // We impose this condition because somebody can make a child frame - // containing a carefully crafted html/javascript in one encoding - // that can be mistaken for hintEncoding (or related encoding) by - // an auto detector. When interpreted in the latter, it could be - // an attack vector. - // FIXME: This might be too cautious for non-7bit-encodings and - // we may consider relaxing this later after testing. - if (canReferToParentFrameEncoding(m_frame, parentFrame)) - m_decoder->setHintEncoding(parentFrame->document()->decoder()); - } else - m_decoder = TextResourceDecoder::create(m_mimeType, String()); - Frame* parentFrame = m_frame->tree()->parent(); - if (m_encoding.isEmpty()) { - if (canReferToParentFrameEncoding(m_frame, parentFrame)) - m_decoder->setEncoding(parentFrame->document()->inputEncoding(), TextResourceDecoder::EncodingFromParentFrame); - } else { - m_decoder->setEncoding(m_encoding, - m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader); - } - m_frame->document()->setDecoder(m_decoder.get()); - } - return m_decoder.get(); -} - -void DocumentWriter::reportDataReceived() -{ - ASSERT(m_decoder); - if (!m_receivedData) { - m_receivedData = true; - if (m_decoder->encoding().usesVisualOrdering()) - m_frame->document()->setVisuallyOrdered(); - m_frame->document()->recalcStyle(Node::Force); - } -} - -void DocumentWriter::addData(const char* str, int len, bool flush) -{ - if (len == -1) - len = strlen(str); - - DocumentParser* parser = m_frame->document()->parser(); - if (parser) - parser->appendBytes(this, str, len, flush); -} - -void DocumentWriter::end() -{ - m_frame->loader()->didEndDocument(); - endIfNotLoadingMainResource(); -} - -void DocumentWriter::endIfNotLoadingMainResource() -{ - if (m_frame->loader()->isLoadingMainResource() || !m_frame->page() || !m_frame->document()) - 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 - addData(0, 0, true); - m_frame->document()->finishParsing(); -} - -String DocumentWriter::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(); -} - -void DocumentWriter::setEncoding(const String& name, bool userChosen) -{ - m_frame->loader()->willSetEncoding(); - m_encoding = name; - m_encodingWasChosenByUser = userChosen; -} - -void DocumentWriter::setDecoder(TextResourceDecoder* decoder) -{ - m_decoder = decoder; -} - -String DocumentWriter::deprecatedFrameEncoding() const -{ - return m_frame->loader()->url().isEmpty() ? m_encoding : encoding(); -} - -void DocumentWriter::setDocumentWasLoadedAsPartOfNavigation() -{ - m_frame->document()->parser()->setDocumentWasLoadedAsPartOfNavigation(); -} - -} // namespace WebCore diff --git a/WebCore/loader/DocumentWriter.h b/WebCore/loader/DocumentWriter.h deleted file mode 100644 index 5fb3dc1..0000000 --- a/WebCore/loader/DocumentWriter.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2010. Adam Barth. 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 Adam Barth. ("Adam Barth") 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 DocumentWriter_h -#define DocumentWriter_h - -#include "KURL.h" -#include "PlatformString.h" - -namespace WebCore { - -class Document; -class Frame; -class SecurityOrigin; -class TextResourceDecoder; - -class DocumentWriter : public Noncopyable { -public: - DocumentWriter(Frame*); - - // This is only called by ScriptController::executeIfJavaScriptURL - // and always contains the result of evaluating a javascript: url. - void replaceDocument(const String&); - - void begin(); - void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0); - void addData(const char* string, int length = -1, bool flush = false); - void end(); - void endIfNotLoadingMainResource(); - void clear(); - - String encoding() const; - void setEncoding(const String& encoding, bool userChosen); - - // FIXME: It's really unforunate to need to expose this piece of state. - // I suspect a better design is to disentangle user-provided encodings, - // default encodings, and the decoding we're currently using. - String deprecatedFrameEncoding() const; - - const String& mimeType() const { return m_mimeType; } - void setMIMEType(const String& type) { m_mimeType = type; } - - void setDecoder(TextResourceDecoder*); - - // Exposed for DoucmentParser::appendBytes - TextResourceDecoder* createDecoderIfNeeded(); - void reportDataReceived(); - - void setDocumentWasLoadedAsPartOfNavigation(); - -private: - PassRefPtr<Document> createDocument(const KURL&); - - Frame* m_frame; - - bool m_receivedData; - String m_mimeType; - - bool m_encodingWasChosenByUser; - String m_encoding; - RefPtr<TextResourceDecoder> m_decoder; -}; - -} // namespace WebCore - -#endif // DocumentWriter_h diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h deleted file mode 100644 index d34be9b..0000000 --- a/WebCore/loader/EmptyClients.h +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Copyright (C) 2006 Eric Seidel (eric@webkit.org) - * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 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. - * - * 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 "Console.h" -#include "ContextMenuClient.h" -#include "DeviceMotionClient.h" -#include "DeviceOrientationClient.h" -#include "DocumentLoader.h" -#include "DragClient.h" -#include "EditCommand.h" -#include "EditorClient.h" -#include "FloatRect.h" -#include "FocusDirection.h" -#include "FrameLoaderClient.h" -#include "FrameNetworkingContext.h" -#include "InspectorClient.h" -#include "PluginHalterClient.h" -#include "PopupMenu.h" -#include "ResourceError.h" -#include "SearchPopupMenu.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 SharedGraphicsContext3D; - -class EmptyPopupMenu : public PopupMenu { -public: - virtual void show(const IntRect&, FrameView*, int) {} - virtual void hide() {} - virtual void updateFromElement() {} - virtual void disconnectClient() {} -}; - -class EmptySearchPopupMenu : public SearchPopupMenu { -public: - virtual PopupMenu* popupMenu() { return m_popup.get(); } - virtual void saveRecentSearches(const AtomicString&, const Vector<String>&) {} - virtual void loadRecentSearches(const AtomicString&, Vector<String>&) {} - virtual bool enabled() { return false; } - -private: - RefPtr<EmptyPopupMenu> m_popup; -}; - -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; } - -#if ENABLE(ANDROID_INSTALLABLE_WEB_APPS) - virtual void webAppCanBeInstalled() { } -#endif - - virtual void focus() { } - virtual void unfocus() { } - - virtual bool canTakeFocus(FocusDirection) { return false; } - virtual void takeFocus(FocusDirection) { } - - virtual void focusedNodeChanged(Node*) { } - virtual void focusedFrameChanged(Frame*) { } - - virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&, const NavigationAction&) { 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(MessageSource, MessageType, MessageLevel, const String&, unsigned, const String&) { } - - virtual bool canRunBeforeUnloadConfirmPanel() { return false; } - virtual bool runBeforeUnloadConfirmPanel(const String&, 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&, const String&, String&) { return false; } - virtual bool shouldInterruptJavaScript() { return false; } - - virtual bool selectItemWritingDirectionIsNatural() { return false; } - virtual PassRefPtr<PopupMenu> createPopupMenu(PopupMenuClient*) const { return adoptRef(new EmptyPopupMenu()); } - virtual PassRefPtr<SearchPopupMenu> createSearchPopupMenu(PopupMenuClient*) const { return adoptRef(new EmptySearchPopupMenu()); } - -#if ENABLE(CONTEXT_MENUS) - virtual void showContextMenu() { } -#endif - - virtual void setStatusbarText(const String&) { } - - virtual bool tabsToLinks() const { return false; } - - virtual IntRect windowResizerRect() const { return IntRect(); } - - virtual void invalidateWindow(const IntRect&, bool) { } - virtual void invalidateContentsAndWindow(const IntRect&, bool) { } - virtual void invalidateContentsForSlowScroll(const IntRect&, bool) {}; - virtual void scroll(const IntSize&, const IntRect&, const IntRect&) { } -#if ENABLE(TILED_BACKING_STORE) - virtual void delegatedScrollRequested(const IntSize&) { } -#endif - - virtual IntPoint screenToWindow(const IntPoint& p) const { return p; } - virtual IntRect windowToScreen(const IntRect& r) const { return r; } - virtual PlatformPageClient platformPageClient() const { return 0; } - virtual void contentsSizeChanged(Frame*, const IntSize&) const { } - - virtual void scrollbarsModeDidChange() const { } - virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned) { } - - virtual void setToolTip(const String&, TextDirection) { } - - virtual void print(Frame*) { } - -#if ENABLE(DATABASE) - virtual void exceededDatabaseQuota(Frame*, const String&) { } -#endif - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - virtual void reachedMaxAppCacheSize(int64_t) { } - virtual void reachedApplicationCacheOriginQuota(SecurityOrigin*) { } -#endif - -#if ENABLE(NOTIFICATIONS) - virtual NotificationPresenter* notificationPresenter() const { return 0; } -#endif - - virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) { } - virtual void chooseIconForFiles(const Vector<String>&, FileChooser*) { } - - virtual void formStateDidChange(const Node*) { } - - virtual void formDidFocus(const Node*) { } - virtual void formDidBlur(const Node*) { } - - virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() { return 0; } - - virtual void setCursor(const Cursor&) { } - - virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const {} - - virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) {} - virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*) {} - -#if USE(ACCELERATED_COMPOSITING) - virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) {} - virtual void setNeedsOneShotDrawingSynchronization() {} - virtual void scheduleCompositingLayerSync() {} -#endif - -#if PLATFORM(WIN) - virtual void setLastSetCursorToCurrentCursor() { } -#endif -#if ENABLE(TOUCH_EVENTS) - virtual void needTouchEvents(bool) { } -#endif -}; - -class EmptyFrameLoaderClient : public FrameLoaderClient, public Noncopyable { -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 setCopiesOnScroll() { } - - virtual void detachedFromParent2() { } - virtual void detachedFromParent3() { } - - virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) { } - - virtual void assignIdentifierToInitialRequest(unsigned long, DocumentLoader*, const ResourceRequest&) { } - virtual bool shouldUseCredentialStorage(DocumentLoader*, unsigned long) { return false; } - virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, const ResourceResponse&) { } - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&) { } - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&) { } -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace&) { return false; } -#endif - virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long, const ResourceResponse&) { } - virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long, int) { } - virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long) { } - virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long, const ResourceError&) { } - virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int) { return false; } - - virtual void dispatchDidHandleOnloadEvents() { } - virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() { } - virtual void dispatchDidCancelClientRedirect() { } - virtual void dispatchWillPerformClientRedirect(const KURL&, double, double) { } - virtual void dispatchDidChangeLocationWithinPage() { } - virtual void dispatchDidPushStateWithinPage() { } - virtual void dispatchDidReplaceStateWithinPage() { } - virtual void dispatchDidPopStateWithinPage() { } - virtual void dispatchWillClose() { } - virtual void dispatchDidReceiveIcon() { } - virtual void dispatchDidStartProvisionalLoad() { } - virtual void dispatchDidReceiveTitle(const String&) { } - virtual void dispatchDidChangeIcons() { } - virtual void dispatchDidCommitLoad() { } - virtual void dispatchDidFailProvisionalLoad(const ResourceError&) { } - virtual void dispatchDidFailLoad(const ResourceError&) { } - virtual void dispatchDidFinishDocumentLoad() { } - virtual void dispatchDidFinishLoad() { } - virtual void dispatchDidFirstLayout() { } - virtual void dispatchDidFirstVisuallyNonEmptyLayout() { } - - virtual Frame* dispatchCreatePage(const NavigationAction&) { return 0; } - virtual void dispatchShow() { } - - virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String&, const ResourceRequest&) { } - virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String&) { } - virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>) { } - virtual void cancelPolicyCheck() { } - - virtual void dispatchUnableToImplementPolicy(const ResourceError&) { } - - virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { } - 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&) { ResourceError error("", 0, "", ""); error.setIsCancellation(true); return error; } - virtual ResourceError blockedError(const ResourceRequest&) { return ResourceError("", 0, "", ""); } - virtual ResourceError cannotShowURLError(const ResourceRequest&) { return ResourceError("", 0, "", ""); } - virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) { return ResourceError("", 0, "", ""); } - - virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) { return ResourceError("", 0, "", ""); } - virtual ResourceError fileDoesNotExistError(const ResourceResponse&) { return ResourceError("", 0, "", ""); } - virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) { return ResourceError("", 0, "", ""); } - - virtual bool shouldFallBack(const ResourceError&) { return false; } - - virtual bool canHandleRequest(const ResourceRequest&) const { return false; } - virtual bool canShowMIMEType(const String&) const { return false; } - virtual bool canShowMIMETypeAsHTML(const String&) const { return false; } - virtual bool representationExistsForURLScheme(const String&) const { return false; } - virtual String generatedMIMETypeForURLScheme(const String&) const { return ""; } - - virtual void frameLoadCompleted() { } - virtual void restoreViewState() { } - virtual void provisionalLoadStarted() { } - virtual bool shouldTreatURLAsSameAsCurrent(const KURL&) const { return false; } - 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&, const KURL&) { } - - virtual String userAgent(const KURL&) { return ""; } - - virtual void savePlatformDataToCachedFrame(CachedFrame*) { } - virtual void transitionToCommittedFromCachedFrame(CachedFrame*) { } - virtual void transitionToCommittedForNewPage() { } - - virtual void dispatchDidBecomeFrameset(bool) { } - - virtual void updateGlobalHistory() { } - virtual void updateGlobalHistoryRedirectLinks() { } - virtual bool shouldGoToHistoryItem(HistoryItem*) const { return false; } - virtual void dispatchDidAddBackForwardItem(HistoryItem*) const { } - virtual void dispatchDidRemoveBackForwardItem(HistoryItem*) const { }; - virtual void dispatchDidChangeBackForwardIndex() const { } - virtual void saveViewStateToItem(HistoryItem*) { } - virtual bool canCachePage() const { return false; } - virtual void didDisplayInsecureContent() { } - virtual void didRunInsecureContent(SecurityOrigin*) { } - virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int) { return 0; } - virtual void didTransferChildFrameToNewDocument(Page*) { } - virtual void transferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*) { } - virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; } - virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; } -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - virtual PassRefPtr<Widget> createMediaPlayerProxyPlugin(const IntSize&, HTMLMediaElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&) { return 0; } - virtual void hideMediaPlayerProxyPlugin(Widget*) { } - virtual void showMediaPlayerProxyPlugin(Widget*) { } -#endif - - virtual ObjectContentType objectContentType(const KURL&, const String&) { return ObjectContentType(); } - virtual String overrideMediaType() const { return String(); } - - virtual void redirectDataToPlugin(Widget*) { } - virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*) { } - virtual void documentElementAvailable() { } - virtual void didPerformFirstNavigation() const { } - -#if USE(V8) - virtual void didCreateScriptContextForFrame() { } - virtual void didDestroyScriptContextForFrame() { } - virtual void didCreateIsolatedScriptContext() { } - virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; } -#endif - - virtual void registerForIconNotification(bool) { } - -#ifdef ANDROID_APPLE_TOUCH_ICON - virtual void dispatchDidReceiveTouchIconURL(const String& url, bool precomposed) { } -#endif - -#if PLATFORM(MAC) - virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long, NSCachedURLResponse* response) const { return response; } -#endif -#if USE(CFNETWORK) - virtual bool shouldCacheResponse(DocumentLoader*, unsigned long, const ResourceResponse&, const unsigned char*, unsigned long long) { return true; } -#endif - - virtual PassRefPtr<FrameNetworkingContext> createNetworkingContext() { return PassRefPtr<FrameNetworkingContext>(); } -}; - -class EmptyEditorClient : public EditorClient, public Noncopyable { -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 isSelectTrailingWhitespaceEnabled() { 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*, Range*, EAffinity, bool) { 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; } - virtual DocumentFragment* documentFragmentFromAttributedString(NSAttributedString*, Vector<RefPtr<ArchiveResource> >&) { return 0; }; - virtual void setInsertionPasteboard(NSPasteboard*) { }; -#ifdef BUILDING_ON_TIGER - virtual NSArray* pasteboardTypesForSelection(Frame*) { return 0; } -#endif -#endif -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - virtual void uppercaseWord() { } - virtual void lowercaseWord() { } - virtual void capitalizeWord() { } - virtual void showSubstitutionsPanel(bool) { } - virtual bool substitutionsPanelIsShowing() { return false; } - virtual void toggleSmartInsertDelete() { } - virtual bool isAutomaticQuoteSubstitutionEnabled() { return false; } - virtual void toggleAutomaticQuoteSubstitution() { } - virtual bool isAutomaticLinkDetectionEnabled() { return false; } - virtual void toggleAutomaticLinkDetection() { } - virtual bool isAutomaticDashSubstitutionEnabled() { return false; } - virtual void toggleAutomaticDashSubstitution() { } - virtual bool isAutomaticTextReplacementEnabled() { return false; } - virtual void toggleAutomaticTextReplacement() { } - virtual bool isAutomaticSpellingCorrectionEnabled() { return false; } - virtual void toggleAutomaticSpellingCorrection() { } -#endif - virtual void ignoreWordInSpellDocument(const String&) { } - virtual void learnWord(const String&) { } - virtual void checkSpellingOfString(const UChar*, int, int*, int*) { } - virtual String getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); } - virtual void checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) { } -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - virtual void checkTextOfParagraph(const UChar*, int, uint64_t, Vector<TextCheckingResult>&) { }; -#endif -#if SUPPORT_AUTOCORRECTION_PANEL - virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect&, const String&, const String&, const Vector<String>&, Editor*) { } - virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) { } - virtual bool isShowingCorrectionPanel() { return false; } -#endif - virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) { } - virtual void updateSpellingUIWithMisspelledWord(const String&) { } - virtual void showSpellingUI(bool) { } - virtual bool spellingUIIsShowing() { return false; } - virtual void getGuessesForWord(const String&, const String&, Vector<String>&) { } - virtual void willSetInputMethodState() { } - virtual void setInputMethodState(bool) { } - virtual void requestCheckingOfString(SpellChecker*, int, const String&) { } -}; - -#if ENABLE(CONTEXT_MENUS) -class EmptyContextMenuClient : public ContextMenuClient, public Noncopyable { -public: - virtual ~EmptyContextMenuClient() { } - virtual void contextMenuDestroyed() { } - -#if USE(CROSS_PLATFORM_CONTEXT_MENUS) - virtual PassOwnPtr<ContextMenu> customizeMenu(PassOwnPtr<ContextMenu>) { return 0; } -#else - virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) { return 0; } -#endif - virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { } - - virtual void downloadURL(const KURL&) { } - virtual void copyImageToClipboard(const HitTestResult&) { } - virtual void searchWithGoogle(const Frame*) { } - virtual void lookUpInDictionary(Frame*) { } - virtual bool isSpeaking() { return false; } - virtual void speak(const String&) { } - virtual void stopSpeaking() { } - -#if PLATFORM(MAC) - virtual void searchWithSpotlight() { } -#endif -}; -#endif // ENABLE(CONTEXT_MENUS) - -#if ENABLE(DRAG_SUPPORT) -class EmptyDragClient : public DragClient, public Noncopyable { -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&, Frame*) { return 0; } - virtual void dragControllerDestroyed() { } -}; -#endif // ENABLE(DRAG_SUPPORT) - -class EmptyInspectorClient : public InspectorClient, public Noncopyable { -public: - virtual ~EmptyInspectorClient() { } - - virtual void inspectorDestroyed() { } - - virtual void openInspectorFrontend(InspectorController*) { } - - virtual void highlight(Node*) { } - virtual void hideHighlight() { } - - virtual void populateSetting(const String&, String*) { } - virtual void storeSetting(const String&, const String&) { } - virtual bool sendMessageToFrontend(const String&) { return false; } -}; - -class EmptyDeviceMotionClient : public DeviceMotionClient { -public: - virtual void setController(DeviceMotionController*) { } - virtual void startUpdating() { } - virtual void stopUpdating() { } - virtual DeviceMotionData* currentDeviceMotion() const { return 0; } - virtual void deviceMotionControllerDestroyed() { } -}; - -class EmptyDeviceOrientationClient : public DeviceOrientationClient { -public: - virtual void setController(DeviceOrientationController*) { } - virtual void startUpdating() { } - virtual void stopUpdating() { } - virtual DeviceOrientation* lastOrientation() const { return 0; } - virtual void deviceOrientationControllerDestroyed() { } -}; - -} - -#endif // EmptyClients_h diff --git a/WebCore/loader/FTPDirectoryParser.cpp b/WebCore/loader/FTPDirectoryParser.cpp deleted file mode 100644 index 6a05c4c..0000000 --- a/WebCore/loader/FTPDirectoryParser.cpp +++ /dev/null @@ -1,1715 +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 OS(WINDOWS) && (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) - -// Replacement for gmtime_r() which is not available on MinGW. -// We use this on Win32 Qt platform for portability. -struct tm gmtimeQt(const QDateTime& input) -{ - tm result; - - 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(); - - QTime time(input.time()); - result.tm_sec = time.second(); - result.tm_min = time.minute(); - result.tm_hour = time.hour(); - - return result; -} - -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 OS(WINDOWS) && !defined(gmtime_r) -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define gmtime_r(x, y) gmtime_s((y), (x)) -#else /* !_MSC_VER */ -#define gmtime_r(x,y) (gmtime(x)?(*(y)=*gmtime(x),(y)):0) -#endif -#endif - -static inline FTPEntryType ParsingFailed(ListState& state) -{ - 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 */ -} - -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[WTF_ARRAY_LENGTH(tokens)]; - 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 < WTF_ARRAY_LENGTH(tokens)) - { - 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++; - } - } - } - - if (!numtoks) - return ParsingFailed(state); - - linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0]; - if (numtoks == WTF_ARRAY_LENGTH(tokens)) - { - 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; -#if OS(WINDOWS) - sscanf(p + 1, "%I64u", &seconds); -#else - sscanf(p + 1, "%llu", &seconds); -#endif - 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)) - { - /* ']' was found and there is at least one character after it */ - ASSERT(*p == ']'); - pos++; - p++; - tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */ - } else { - /* not a CMU style listing */ - lstyle = 0; - } - } - 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 == 0 || 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]); /* line end */ - result.caseSensitive = true; - result.filename = tokens[3]; - result.filenameLength = p - tokens[3]; - result.type = FTPDirectoryEntry; - - if (*tokens[2] != '<') /* not <DIR> or <JUNCTION> */ - { - // try to handle correctly spaces at the beginning of the filename - // filesize (token[2]) must end at offset 38 - if (tokens[2] + toklen[2] - line == 38) { - result.filename = &(line[39]); - result.filenameLength = p - result.filename; - } - result.type = FTPFileEntry; - pos = toklen[2]; - result.fileSize = String(tokens[2], pos); - } - else { - // try to handle correctly spaces at the beginning of the filename - // token[2] must begin at offset 24, the length is 5 or 10 - // token[3] must begin at offset 39 or higher - if (tokens[2] - line == 24 && (toklen[2] == 5 || toklen[2] == 10) && - tokens[3] - line >= 39) { - result.filename = &(line[39]); - result.filenameLength = p - result.filename; - } - - 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]) - - 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 year has only two digits then assume that - 00-79 is 2000-2079 - 80-99 is 1980-1999 */ - if (result.modifiedTime.tm_year < 80) - result.modifiedTime.tm_year += 2000; - else if (result.modifiedTime.tm_year < 100) - result.modifiedTime.tm_year += 1900; - } - - 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" - */ - - bool isOldHellsoft = false; - - 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 */ - if (toklen[0] == 10) - isOldHellsoft = true; - } - } - } - 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 (unsigned int i = 0; lstyle && i < toklen[tokmarker]; ++i) - { - if (!isASCIIDigit(*p++)) - lstyle = 0; - } - if (lstyle) - { - month_num = 0; - p = tokens[tokmarker+1]; - for (unsigned int i = 0; i < (12*3); i+=3) - { - if (p[0] == month_names[i+0] && - p[1] == month_names[i+1] && - p[2] == month_names[i+2]) - break; - month_num++; - } - if (month_num >= 12) - lstyle = 0; - } - } /* relative position test */ - } /* for (pos = (numtoks-5); !lstyle && pos > 1; pos--) */ - } /* if (lstyle == 'U') */ - - 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 */ - - // there is exactly 1 space between filename and previous token in all - // outputs except old Hellsoft - if (!isOldHellsoft) - result.filename = tokens[tokmarker+3] + toklen[tokmarker+3] + 1; - else - result.filename = tokens[tokmarker+4]; - - result.filenameLength = (&(line[linelen])) - - (result.filename); - - if (result.type == FTPLinkEntry && result.filenameLength > 4) - { - /* First try to use result.fe_size to find " -> " sequence. - This can give proper result for cases like "aaa -> bbb -> ccc". */ - unsigned int fileSize = result.fileSize.toUInt(); - - if (result.filenameLength > (fileSize + 4) && - strncmp(result.filename + result.filenameLength - fileSize - 4, " -> ", 4) == 0) - { - result.linkname = result.filename + (result.filenameLength - fileSize); - result.linknameLength = (&(line[linelen])) - (result.linkname); - result.filenameLength -= fileSize + 4; - } - else - { - /* Search for sequence " -> " from the end for case when there are - more occurrences. F.e. if ftpd returns "a -> b -> c" assume - "a -> b" as a name. Powerusers can remove unnecessary parts - manually but there is no way to follow the link when some - essential part is missing. */ - p = result.filename + (result.filenameLength - 5); - for (pos = (result.filenameLength - 5); pos > 0; pos--) - { - if (strncmp(p, " -> ", 4) == 0) - { - result.linkname = p + 4; - result.linknameLength = (&(line[linelen])) - - (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) */ - - return ParsingFailed(state); -} - -} // 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 552789a..0000000 --- a/WebCore/loader/FormState.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2006, 2009 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 "FormState.h" - -#include "Frame.h" -#include "HTMLFormElement.h" - -namespace WebCore { - -inline FormState::FormState(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger) - : m_form(form) - , m_sourceFrame(sourceFrame) - , m_formSubmissionTrigger(formSubmissionTrigger) -{ - m_textFieldValues.swap(textFieldValuesToAdopt); -} - -PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger) -{ - return adoptRef(new FormState(form, textFieldValuesToAdopt, sourceFrame, formSubmissionTrigger)); -} - -} diff --git a/WebCore/loader/FormState.h b/WebCore/loader/FormState.h deleted file mode 100644 index 8f7166e..0000000 --- a/WebCore/loader/FormState.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2006, 2009 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 FormState_h -#define FormState_h - -#include "PlatformString.h" - -namespace WebCore { - - class Frame; - class HTMLFormElement; - - enum FormSubmissionTrigger { - SubmittedByJavaScript, - NotSubmittedByJavaScript - }; - - typedef Vector<std::pair<String, String> > StringPairVector; - - class FormState : public RefCounted<FormState> { - public: - static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger); - - HTMLFormElement* form() const { return m_form.get(); } - const StringPairVector& textFieldValues() const { return m_textFieldValues; } - Frame* sourceFrame() const { return m_sourceFrame.get(); } - FormSubmissionTrigger formSubmissionTrigger() const { return m_formSubmissionTrigger; } - - private: - FormState(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger); - - RefPtr<HTMLFormElement> m_form; - StringPairVector m_textFieldValues; - RefPtr<Frame> m_sourceFrame; - FormSubmissionTrigger m_formSubmissionTrigger; - }; - -} - -#endif // FormState_h diff --git a/WebCore/loader/FormSubmission.cpp b/WebCore/loader/FormSubmission.cpp deleted file mode 100644 index 44f9ff1..0000000 --- a/WebCore/loader/FormSubmission.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "FormSubmission.h" - -#include "DOMFormData.h" -#include "Document.h" -#include "Event.h" -#include "FormData.h" -#include "FormDataBuilder.h" -#include "FormState.h" -#include "Frame.h" -#include "FrameLoadRequest.h" -#include "FrameLoader.h" -#include "HTMLFormControlElement.h" -#include "HTMLFormElement.h" -#include "HTMLInputElement.h" -#include "HTMLNames.h" -#include "HTMLParserIdioms.h" -#include "TextEncoding.h" -#include <wtf/CurrentTime.h> -#include <wtf/RandomNumber.h> - -namespace WebCore { - -using namespace HTMLNames; - -static int64_t generateFormDataIdentifier() -{ - // Initialize to the current time to reduce the likelihood of generating - // identifiers that overlap with those from past/future browser sessions. - static int64_t nextIdentifier = static_cast<int64_t>(currentTime() * 1000000.0); - return ++nextIdentifier; -} - -static void appendMailtoPostFormDataToURL(KURL& url, const FormData& data, const String& encodingType) -{ - String body = data.flattenToString(); - - if (equalIgnoringCase(encodingType, "text/plain")) { - // Convention seems to be to decode, and s/&/\r\n/. Also, spaces are encoded as %20. - body = decodeURLEscapeSequences(body.replace('&', "\r\n").replace('+', ' ') + "\r\n"); - } - - Vector<char> bodyData; - bodyData.append("body=", 5); - FormDataBuilder::encodeStringAsFormData(bodyData, body.utf8()); - body = String(bodyData.data(), bodyData.size()).replace('+', "%20"); - - String query = url.query(); - if (!query.isEmpty()) - query.append('&'); - query.append(body); - url.setQuery(query); -} - -void FormSubmission::Attributes::parseAction(const String& action) -{ - // FIXME: Can we parse into a KURL? - m_action = stripLeadingAndTrailingHTMLSpaces(action); -} - -void FormSubmission::Attributes::parseEncodingType(const String& type) -{ - if (type.contains("multipart", false) || type.contains("form-data", false)) { - m_encodingType = "multipart/form-data"; - m_isMultiPartForm = true; - } else if (type.contains("text", false) || type.contains("plain", false)) { - m_encodingType = "text/plain"; - m_isMultiPartForm = false; - } else { - m_encodingType = "application/x-www-form-urlencoded"; - m_isMultiPartForm = false; - } -} - -void FormSubmission::Attributes::parseMethodType(const String& type) -{ - if (equalIgnoringCase(type, "post")) - m_method = FormSubmission::PostMethod; - else if (equalIgnoringCase(type, "get")) - m_method = FormSubmission::GetMethod; -} - -void FormSubmission::Attributes::copyFrom(const Attributes& other) -{ - m_method = other.m_method; - m_isMultiPartForm = other.m_isMultiPartForm; - - m_action = other.m_action; - m_target = other.m_target; - m_encodingType = other.m_encodingType; - m_acceptCharset = other.m_acceptCharset; -} - -inline FormSubmission::FormSubmission(Method method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState> state, PassRefPtr<FormData> data, const String& boundary, bool lockHistory, PassRefPtr<Event> event) - : m_method(method) - , m_action(action) - , m_target(target) - , m_contentType(contentType) - , m_formState(state) - , m_formData(data) - , m_boundary(boundary) - , m_lockHistory(lockHistory) - , m_event(event) -{ -} - -PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger trigger) -{ - ASSERT(form); - - HTMLFormControlElement* submitButton = 0; - if (event && event->target() && event->target()->toNode()) - submitButton = static_cast<HTMLFormControlElement*>(event->target()->toNode()); - - FormSubmission::Attributes copiedAttributes; - copiedAttributes.copyFrom(attributes); - if (submitButton) { - String attributeValue; - if (!(attributeValue = submitButton->getAttribute(formactionAttr)).isNull()) - copiedAttributes.parseAction(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formenctypeAttr)).isNull()) - copiedAttributes.parseEncodingType(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formmethodAttr)).isNull()) - copiedAttributes.parseMethodType(attributeValue); - if (!(attributeValue = submitButton->getAttribute(formtargetAttr)).isNull()) - copiedAttributes.setTarget(attributeValue); - } - - Document* document = form->document(); - KURL actionURL = document->completeURL(copiedAttributes.action().isEmpty() ? document->url().string() : copiedAttributes.action()); - bool isMailtoForm = actionURL.protocolIs("mailto"); - bool isMultiPartForm = false; - String encodingType = copiedAttributes.encodingType(); - - if (copiedAttributes.method() == PostMethod) { - isMultiPartForm = copiedAttributes.isMultiPartForm(); - if (isMultiPartForm && isMailtoForm) { - encodingType = "application/x-www-form-urlencoded"; - isMultiPartForm = false; - } - } - - TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataBuilder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document); - RefPtr<DOMFormData> domFormData = DOMFormData::create(dataEncoding.encodingForFormSubmission()); - Vector<pair<String, String> > formValues; - - for (unsigned i = 0; i < form->associatedElements().size(); ++i) { - FormAssociatedElement* control = form->associatedElements()[i]; - HTMLElement* element = toHTMLElement(control); - if (!element->disabled()) - control->appendFormData(*domFormData, isMultiPartForm); - if (element->hasLocalName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(control); - if (input->isTextField()) { - formValues.append(pair<String, String>(input->name(), input->value())); - if (input->isSearchField()) - input->addSearchResult(); - } - } - } - - RefPtr<FormData> formData; - String boundary; - - if (isMultiPartForm) { - formData = FormData::createMultiPart(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding(), document); - boundary = formData->boundary().data(); - } else { - formData = FormData::create(*(static_cast<FormDataList*>(domFormData.get())), domFormData->encoding()); - if (copiedAttributes.method() == PostMethod && isMailtoForm) { - // Convert the form data into a string that we put into the URL. - appendMailtoPostFormDataToURL(actionURL, *formData, encodingType); - formData = FormData::create(); - } - } - - formData->setIdentifier(generateFormDataIdentifier()); - String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document->baseTarget() : copiedAttributes.target(); - RefPtr<FormState> formState = FormState::create(form, formValues, document->frame(), trigger); - return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event)); -} - -KURL FormSubmission::requestURL() const -{ - if (m_method == FormSubmission::PostMethod) - return m_action; - - KURL requestURL(m_action); - requestURL.setQuery(m_formData->flattenToString()); - return requestURL; -} - -void FormSubmission::populateFrameLoadRequest(FrameLoadRequest& frameRequest) -{ - if (!m_target.isEmpty()) - frameRequest.setFrameName(m_target); - - if (!m_referrer.isEmpty()) - frameRequest.resourceRequest().setHTTPReferrer(m_referrer); - - if (m_method == FormSubmission::PostMethod) { - frameRequest.resourceRequest().setHTTPMethod("POST"); - frameRequest.resourceRequest().setHTTPBody(m_formData); - - // construct some user headers if necessary - if (m_contentType.isNull() || m_contentType == "application/x-www-form-urlencoded") - frameRequest.resourceRequest().setHTTPContentType(m_contentType); - else // contentType must be "multipart/form-data" - frameRequest.resourceRequest().setHTTPContentType(m_contentType + "; boundary=" + m_boundary); - } - - frameRequest.resourceRequest().setURL(requestURL()); - FrameLoader::addHTTPOriginIfNeeded(frameRequest.resourceRequest(), m_origin); -} - -} diff --git a/WebCore/loader/FormSubmission.h b/WebCore/loader/FormSubmission.h deleted file mode 100644 index d724835..0000000 --- a/WebCore/loader/FormSubmission.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 FormSubmission_h -#define FormSubmission_h - -#include "FormState.h" -#include "KURL.h" - -namespace WebCore { - -class Document; -class Event; -class FormData; -struct FrameLoadRequest; -class HTMLFormElement; -class TextEncoding; - -class FormSubmission : public RefCounted<FormSubmission> { -public: - enum Method { GetMethod, PostMethod }; - - class Attributes : public Noncopyable { - public: - Attributes() - : m_method(GetMethod) - , m_isMultiPartForm(false) - , m_encodingType("application/x-www-form-urlencoded") - { - } - - Method method() const { return m_method; } - void parseMethodType(const String&); - - const String& action() const { return m_action; } - void parseAction(const String&); - - const String& target() const { return m_target; } - void setTarget(const String& target) { m_target = target; } - - const String& encodingType() const { return m_encodingType; } - void parseEncodingType(const String&); - bool isMultiPartForm() const { return m_isMultiPartForm; } - - const String& acceptCharset() const { return m_acceptCharset; } - void setAcceptCharset(const String& value) { m_acceptCharset = value; } - - void copyFrom(const Attributes&); - - private: - Method m_method; - bool m_isMultiPartForm; - - String m_action; - String m_target; - String m_encodingType; - String m_acceptCharset; - }; - - static PassRefPtr<FormSubmission> create(HTMLFormElement*, const Attributes&, PassRefPtr<Event> event, bool lockHistory, FormSubmissionTrigger); - - void populateFrameLoadRequest(FrameLoadRequest&); - - KURL requestURL() const; - - Method method() const { return m_method; } - const KURL& action() const { return m_action; } - const String& target() const { return m_target; } - void clearTarget() { m_target = String(); } - const String& contentType() const { return m_contentType; } - FormState* state() const { return m_formState.get(); } - FormData* data() const { return m_formData.get(); } - const String boundary() const { return m_boundary; } - bool lockHistory() const { return m_lockHistory; } - Event* event() const { return m_event.get(); } - - const String& referrer() const { return m_referrer; } - void setReferrer(const String& referrer) { m_referrer = referrer; } - const String& origin() const { return m_origin; } - void setOrigin(const String& origin) { m_origin = origin; } - -private: - FormSubmission(Method, const KURL& action, const String& target, const String& contentType, PassRefPtr<FormState>, PassRefPtr<FormData>, const String& boundary, bool lockHistory, PassRefPtr<Event>); - - // FIXME: Hold an instance of Attributes instead of individual members. - Method m_method; - KURL m_action; - String m_target; - String m_contentType; - RefPtr<FormState> m_formState; - RefPtr<FormData> m_formData; - String m_boundary; - bool m_lockHistory; - RefPtr<Event> m_event; - String m_referrer; - String m_origin; -}; - -} - -#endif // FormSubmission_h diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp deleted file mode 100644 index d4b65a9..0000000 --- a/WebCore/loader/FrameLoader.cpp +++ /dev/null @@ -1,3531 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) 2008 Alp Toker <alp@atoker.com> - * Copyright (C) Research In Motion Limited 2009. 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 "FrameLoader.h" - -#include "ApplicationCacheHost.h" -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -#include "Archive.h" -#include "ArchiveFactory.h" -#endif -#include "BackForwardController.h" -#include "BeforeUnloadEvent.h" -#include "MemoryCache.h" -#include "CachedPage.h" -#include "CachedResourceLoader.h" -#include "Chrome.h" -#include "DOMImplementation.h" -#include "DOMWindow.h" -#include "Document.h" -#include "DocumentLoadTiming.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 "FormSubmission.h" -#include "Frame.h" -#include "FrameLoadRequest.h" -#include "FrameLoaderClient.h" -#include "FrameNetworkingContext.h" -#include "FrameTree.h" -#include "FrameView.h" -#include "HTMLAnchorElement.h" -#include "HTMLFormElement.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 "PageTransitionEvent.h" -#include "PluginData.h" -#include "PluginDatabase.h" -#include "PluginDocument.h" -#include "ProgressTracker.h" -#include "ResourceHandle.h" -#include "ResourceRequest.h" -#include "SchemeRegistry.h" -#include "ScriptController.h" -#include "ScriptSourceCode.h" -#include "SecurityOrigin.h" -#include "SegmentedString.h" -#include "SerializedScriptValue.h" -#include "Settings.h" -#include "TextResourceDecoder.h" -#include "WindowFeatures.h" -#include "XMLDocumentParser.h" -#include <wtf/CurrentTime.h> -#include <wtf/StdLibExtras.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringConcatenate.h> - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "HTMLMediaElement.h" -#endif - -#if ENABLE(SHARED_WORKERS) -#include "SharedWorkerRepository.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" -#include "RenderArena.h" -#endif - -namespace WebCore { - -using namespace HTMLNames; - -#if ENABLE(SVG) -using namespace SVGNames; -#endif - -#if ENABLE(XHTMLMP) -static const char defaultAcceptHeader[] = "application/xml,application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; -#else -static const char defaultAcceptHeader[] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; -#endif - -static double storedTimeOfLastCompletedLoad; - -bool isBackForwardLoadType(FrameLoadType type) -{ - switch (type) { - case FrameLoadTypeStandard: - case FrameLoadTypeReload: - case FrameLoadTypeReloadFromOrigin: - case FrameLoadTypeSame: - case FrameLoadTypeRedirectWithLockedBackForwardList: - case FrameLoadTypeReplace: - return false; - case FrameLoadTypeBack: - case FrameLoadTypeBackWMLDeckNotAccessible: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - return true; - } - ASSERT_NOT_REACHED(); - return false; -} - -static int numRequests(Document* document) -{ - if (!document) - return 0; - - return document->cachedResourceLoader()->requestCount(); -} - -// This is not in the FrameLoader class to emphasize that it does not depend on -// private FrameLoader data, and to avoid increasing the number of public functions -// with access to private data. Since only this .cpp file needs it, making it -// non-member lets us exclude it from the header file, thus keeping FrameLoader.h's -// API simpler. -// -// FIXME: isDocumentSandboxed should eventually replace isSandboxed. -static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask) -{ - return frame->document() && frame->document()->securityOrigin()->isSandboxed(mask); -} - -FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) - : m_frame(frame) - , m_client(client) - , m_policyChecker(frame) - , m_history(frame) - , m_notifer(frame) - , m_writer(frame) - , m_subframeLoader(frame) - , m_state(FrameStateCommittedPage) - , m_loadType(FrameLoadTypeStandard) - , m_delegateIsHandlingProvisionalLoadError(false) - , m_quickRedirectComing(false) - , m_sentRedirectNotification(false) - , m_inStopAllLoaders(false) - , m_isExecutingJavaScriptFormAction(false) - , m_didCallImplicitClose(false) - , m_wasUnloadEventEmitted(false) - , m_pageDismissalEventBeingDispatched(false) - , m_isComplete(false) - , m_isLoadingMainResource(false) - , m_needsClear(false) - , m_checkTimer(this, &FrameLoader::checkTimerFired) - , m_shouldCallCheckCompleted(false) - , m_shouldCallCheckLoadComplete(false) - , m_opener(0) - , m_didPerformFirstNavigation(false) - , m_loadingFromCachedPage(false) - , m_suppressOpenerInNewFrame(false) - , m_sandboxFlags(SandboxAll) - , m_forcedSandboxFlags(SandboxNone) -{ -} - -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(); - - if (m_networkingContext) - m_networkingContext->invalidate(); -} - -void FrameLoader::init() -{ - // Propagate sandbox attributes to this Frameloader and its descendants. - // This needs to be done early, so that an initial document gets correct sandbox flags in its SecurityOrigin. - updateSandboxFlags(); - - // this somewhat odd set of steps is needed to give the frame an initial empty document - m_stateMachine.advanceTo(FrameLoaderStateMachine::CreatingInitialEmptyDocument); - setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get()); - setProvisionalDocumentLoader(m_policyDocumentLoader.get()); - setState(FrameStateProvisional); - m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String())); - m_provisionalDocumentLoader->finishedLoading(); - writer()->begin(KURL(), false); - writer()->end(); - m_frame->document()->cancelParsing(); - m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument); - m_didCallImplicitClose = true; - - m_networkingContext = m_client->createNetworkingContext(); -} - -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); - - if (!defers) { - m_frame->navigationScheduler()->startTimer(); - startCheckCompleteTimer(); - } -} - -bool FrameLoader::canHandleRequest(const ResourceRequest& request) -{ - return m_client->canHandleRequest(request); -} - -void FrameLoader::changeLocation(PassRefPtr<SecurityOrigin> securityOrigin, const KURL& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool refresh) -{ - RefPtr<Frame> protect(m_frame); - urlSelected(FrameLoadRequest(securityOrigin, ResourceRequest(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy), "_self"), - 0, lockHistory, lockBackForwardList, SendReferrer, ReplaceDocumentIfJavaScriptURL); -} - -void FrameLoader::urlSelected(const KURL& url, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy) -{ - urlSelected(FrameLoadRequest(m_frame->document()->securityOrigin(), ResourceRequest(url), passedTarget), - triggeringEvent, lockHistory, lockBackForwardList, referrerPolicy, DoNotReplaceDocumentIfJavaScriptURL); -} - -// The shouldReplaceDocumentIfJavaScriptURL parameter will go away when the FIXME to eliminate the -// corresponding parameter from ScriptController::executeIfJavaScriptURL() is addressed. -void FrameLoader::urlSelected(const FrameLoadRequest& passedRequest, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL) -{ - ASSERT(!m_suppressOpenerInNewFrame); - - FrameLoadRequest frameRequest(passedRequest); - - if (m_frame->script()->executeIfJavaScriptURL(frameRequest.resourceRequest().url(), shouldReplaceDocumentIfJavaScriptURL)) - return; - - if (frameRequest.frameName().isEmpty()) - frameRequest.setFrameName(m_frame->document()->baseTarget()); - - if (referrerPolicy == NoReferrer) - m_suppressOpenerInNewFrame = true; - if (frameRequest.resourceRequest().httpReferrer().isEmpty()) - frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); - addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); - - loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy); - - m_suppressOpenerInNewFrame = false; -} - -void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission) -{ - ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod); - - // FIXME: Find a good spot for these. - ASSERT(submission->data()); - ASSERT(submission->state()); - ASSERT(submission->state()->sourceFrame() == m_frame); - - if (!m_frame->page()) - return; - - if (submission->action().isEmpty()) - return; - - if (isDocumentSandboxed(m_frame, SandboxForms)) - return; - - if (protocolIsJavaScript(submission->action())) { - m_isExecutingJavaScriptFormAction = true; - m_frame->script()->executeIfJavaScriptURL(submission->action(), DoNotReplaceDocumentIfJavaScriptURL); - m_isExecutingJavaScriptFormAction = false; - return; - } - - Frame* targetFrame = m_frame->tree()->find(submission->target()); - if (!shouldAllowNavigation(targetFrame)) - return; - if (!targetFrame) { - if (!DOMWindow::allowPopUp(m_frame) && !isProcessingUserGesture()) - return; - - targetFrame = m_frame; - } else - submission->clearTarget(); - - if (!targetFrame->page()) - return; - - // 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. - - if (m_frame->tree()->isDescendantOf(targetFrame)) { - if (m_submittedFormURL == submission->action()) - return; - m_submittedFormURL = submission->action(); - } - - submission->data()->generateFiles(m_frame->document()); - submission->setReferrer(m_outgoingReferrer); - submission->setOrigin(outgoingOrigin()); - - targetFrame->navigationScheduler()->scheduleFormSubmission(submission); -} - -void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolicy databasePolicy) -{ - if (m_frame->document() && m_frame->document()->parser()) - m_frame->document()->parser()->stopParsing(); - - if (unloadEventPolicy != UnloadEventPolicyNone) { - if (m_frame->document()) { - if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) { - Node* currentFocusedNode = m_frame->document()->focusedNode(); - if (currentFocusedNode) - currentFocusedNode->aboutToUnload(); - m_pageDismissalEventBeingDispatched = true; - if (m_frame->domWindow()) { - if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) - m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document()); - if (!m_frame->document()->inPageCache()) { - RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false)); - // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed - // while dispatching the event, so protect it to prevent writing the end - // time into freed memory. - if (RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader) { - DocumentLoadTiming* timing = documentLoader->timing(); - ASSERT(timing->navigationStart); - ASSERT(!timing->unloadEventStart); - ASSERT(!timing->unloadEventEnd); - m_frame->domWindow()->dispatchTimedEvent(unloadEvent, m_frame->domWindow()->document(), &timing->unloadEventStart, &timing->unloadEventEnd); - ASSERT(timing->unloadEventStart >= timing->navigationStart); - } else - m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->domWindow()->document()); - } - } - m_pageDismissalEventBeingDispatched = false; - if (m_frame->document()) - m_frame->document()->updateStyleIfNeeded(); - m_wasUnloadEventEmitted = true; - } - } - - // Dispatching the unload event could have made m_frame->document() null. - if (m_frame->document() && !m_frame->document()->inPageCache()) { - // Don't remove event listeners from a transitional empty document (see bug 28716 for more information). - bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader - && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url()); - - if (!keepEventListeners) - m_frame->document()->removeAllEventListeners(); - } - } - - m_isComplete = true; // to avoid calling completed() in finishedParsing() - m_isLoadingMainResource = false; - m_didCallImplicitClose = true; // don't want that one either - - if (m_frame->document() && m_frame->document()->parsing()) { - finishedParsing(); - m_frame->document()->setParsing(false); - } - - m_workingURL = KURL(); - - if (Document* doc = m_frame->document()) { - // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior. - // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537 - doc->setReadyState(Document::Complete); - - if (CachedResourceLoader* cachedResourceLoader = doc->cachedResourceLoader()) - cachedResourceLoader->cancelRequests(); - -#if ENABLE(DATABASE) - if (databasePolicy == DatabasePolicyStop) - doc->stopDatabases(0); -#else - UNUSED_PARAM(databasePolicy); -#endif - } - - // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache. - m_frame->navigationScheduler()->cancel(); -} - -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()->parser()) - m_frame->document()->parser()->stopParsing(); - m_frame->document()->finishParsing(); - - if (m_iconLoader) - m_iconLoader->stopLoading(); -} - -bool FrameLoader::closeURL() -{ - history()->saveDocumentState(); - - // Should only send the pagehide event here if the current document exists and has not been placed in the page cache. - Document* currentDocument = m_frame->document(); - stopLoading(currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly); - - m_frame->editor()->clearUndoRedoOperations(); - return true; -} - -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()->iconURL().isEmpty()) - return KURL(ParsedURLString, m_frame->document()->iconURL()); - - // Don't return a favicon iconURL unless we're http or https - if (!m_URL.protocolInHTTPFamily()) - return KURL(); - - KURL url; - bool couldSetProtocol = url.setProtocol(m_URL.protocol()); - ASSERT_UNUSED(couldSetProtocol, couldSetProtocol); - url.setHost(m_URL.host()); - if (m_URL.hasPort()) - url.setPort(m_URL.port()); - url.setPath("/favicon.ico"); - return url; -} - -bool FrameLoader::didOpenURL(const KURL& url) -{ - if (m_frame->navigationScheduler()->redirectScheduledDuringLoad()) { - // A redirect was scheduled before the document was created. - // This can happen when one frame changes another frame's location. - return false; - } - - m_frame->navigationScheduler()->cancel(); - m_frame->editor()->clearLastEditCommand(); - - m_isComplete = false; - m_isLoadingMainResource = true; - m_didCallImplicitClose = false; - - // If we are still in the process of initializing an empty document then - // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText - // since it may cause clients to attempt to render the frame. - if (!m_stateMachine.creatingInitialEmptyDocument()) { - if (DOMWindow* window = m_frame->existingDOMWindow()) { - window->setStatus(String()); - window->setDefaultStatus(String()); - } - } - m_URL = url; - if (m_URL.protocolInHTTPFamily() && !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. - if (!m_stateMachine.committedFirstRealDocumentLoad()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); - - // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results - // from a subsequent window.document.open / window.document.write call. - // Canceling redirection here works for all cases because document.open - // implicitly precedes document.write. - m_frame->navigationScheduler()->cancel(); - if (m_frame->document()->url() != blankURL()) - m_URL = m_frame->document()->url(); -} - - -void FrameLoader::cancelAndClear() -{ - m_frame->navigationScheduler()->cancel(); - - if (!m_isComplete) - closeURL(); - - clear(false); - m_frame->script()->updatePlatformScriptObjects(); -} - -void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView) -{ - m_frame->editor()->clear(); - - if (!m_needsClear) - return; - m_needsClear = false; - - if (!m_frame->document()->inPageCache()) { - m_frame->document()->cancelParsing(); - m_frame->document()->stopActiveDOMObjects(); - 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->document()->inPageCache()); - } - - m_frame->selection()->clear(); - m_frame->eventHandler()->clear(); - if (clearFrameView && m_frame->view()) - m_frame->view()->clear(); - - // 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); - writer()->clear(); - - m_subframeLoader.clear(); - - if (clearScriptObjects) - m_frame->script()->clearScriptObjects(); - - m_frame->navigationScheduler()->clear(); - - m_checkTimer.stop(); - m_shouldCallCheckCompleted = false; - m_shouldCallCheckLoadComplete = false; - - if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); -} - -void FrameLoader::receivedFirstData() -{ - writer()->begin(m_workingURL, false); - writer()->setDocumentWasLoadedAsPartOfNavigation(); - - dispatchDidCommitLoad(); - dispatchDidClearWindowObjectsInAllWorlds(); - - if (m_documentLoader) { - String ptitle = m_documentLoader->title(); - // If we have a title let the WebView know about it. - if (!ptitle.isNull()) - m_client->dispatchDidReceiveTitle(ptitle); - } - - m_workingURL = KURL(); - - double delay; - String url; - if (!m_documentLoader) - return; - if (m_frame->inViewSourceMode()) - 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(); - - m_frame->navigationScheduler()->scheduleRedirect(delay, url); -} - -void FrameLoader::setURL(const KURL& url) -{ - KURL ref(url); - ref.setUser(String()); - ref.setPass(String()); - ref.removeFragmentIdentifier(); - m_outgoingReferrer = ref.string(); - m_URL = url; -} - -void FrameLoader::didBeginDocument(bool dispatch) -{ - m_needsClear = true; - m_isComplete = false; - m_didCallImplicitClose = false; - m_isLoadingMainResource = true; - m_frame->document()->setReadyState(Document::Loading); - - if (m_pendingStateObject) { - m_frame->document()->statePopped(m_pendingStateObject.get()); - m_pendingStateObject.clear(); - } - - if (dispatch) - dispatchDidClearWindowObjectsInAllWorlds(); - - updateFirstPartyForCookies(); - - Settings* settings = m_frame->document()->settings(); - m_frame->document()->cachedResourceLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically()); -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - m_frame->document()->cachedResourceLoader()->setBlockNetworkImage(settings && settings->blockNetworkImage()); -#endif - - if (m_documentLoader) { - String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control"); - if (!dnsPrefetchControl.isEmpty()) - m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl); - } - - history()->restoreDocumentState(); -} - -void FrameLoader::didEndDocument() -{ - m_isLoadingMainResource = false; -} - -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 && loadType() != FrameLoadTypeReloadFromOrigin) { - 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; - } - } - - // People who want to avoid loading images generally want to avoid loading all images. - // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically. - Settings* settings = m_frame->settings(); - if (settings && !settings->loadsImagesAutomatically()) - 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 = IconLoader::create(m_frame); - - m_iconLoader->startLoading(); -} - -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::finishedParsing() -{ - if (m_stateMachine.creatingInitialEmptyDocument()) - return; - - m_frame->injectUserScripts(InjectAtDocumentEnd); - - // 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; - - m_client->dispatchDidFinishDocumentLoad(); - - 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_frame->view()->scrollToFragment(m_URL); -} - -void FrameLoader::loadDone() -{ - checkCompleted(); -} - -bool FrameLoader::allChildrenAreComplete() const -{ - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { - if (!child->loader()->m_isComplete) - return false; - } - return true; -} - -bool FrameLoader::allAncestorsAreComplete() const -{ - for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) { - if (!ancestor->loader()->m_isComplete) - return false; - } - return true; -} - -void FrameLoader::checkCompleted() -{ - m_shouldCallCheckCompleted = false; - - if (m_frame->view()) - m_frame->view()->checkStopDelayingDeferredRepaints(); - - // Any frame that hasn't completed yet? - if (!allChildrenAreComplete()) - return; - - // Have we completed before? - if (m_isComplete) - return; - - // Are we still parsing? - if (m_frame->document()->parsing()) - return; - - // Still waiting for images/scripts? - if (numRequests(m_frame->document())) - return; - - // Still waiting for elements that don't go through a FrameLoader? - if (m_frame->document()->isDelayingLoadEvent()) - return; - - // OK, completed. - m_isComplete = true; - m_frame->document()->setReadyState(Document::Complete); - - RefPtr<Frame> protect(m_frame); - checkCallImplicitClose(); // if we didn't do it before - - m_frame->navigationScheduler()->startTimer(); - - completed(); - if (m_frame->page()) - checkLoadComplete(); -} - -void FrameLoader::checkTimerFired(Timer<FrameLoader>*) -{ - if (Page* page = m_frame->page()) { - if (page->defersLoading()) - return; - } - if (m_shouldCallCheckCompleted) - checkCompleted(); - if (m_shouldCallCheckLoadComplete) - checkLoadComplete(); -} - -void FrameLoader::startCheckCompleteTimer() -{ - if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete)) - return; - if (m_checkTimer.isActive()) - return; - m_checkTimer.startOneShot(0); -} - -void FrameLoader::scheduleCheckCompleted() -{ - m_shouldCallCheckCompleted = true; - startCheckCompleteTimer(); -} - -void FrameLoader::scheduleCheckLoadComplete() -{ - m_shouldCallCheckLoadComplete = true; - startCheckCompleteTimer(); -} - -void FrameLoader::checkCallImplicitClose() -{ - if (m_didCallImplicitClose || m_frame->document()->parsing() || m_frame->document()->isDelayingLoadEvent()) - return; - - if (!allChildrenAreComplete()) - return; // still got a frame running -> too early - - m_didCallImplicitClose = true; - m_wasUnloadEventEmitted = false; - m_frame->document()->implicitClose(); -} - -KURL FrameLoader::baseURL() const -{ - ASSERT(m_frame->document()); - return m_frame->document()->baseURL(); -} - -KURL FrameLoader::completeURL(const String& url) -{ - ASSERT(m_frame->document()); - return m_frame->document()->completeURL(url); -} - -void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame) -{ - ASSERT(childFrame); - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->uniqueName()); - if (subframeArchive) { - childFrame->loader()->loadArchive(subframeArchive.release()); - return; - } -#endif - - HistoryItem* parentItem = history()->currentItem(); - // If we're moving in the back/forward list, we might want to replace the content - // of this child frame with whatever was there at that point. - if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType())) { - HistoryItem* childItem = parentItem->childItemWithTarget(childFrame->tree()->uniqueName()); - if (childItem) { - childFrame->loader()->loadDifferentDocumentItem(childItem, loadType()); - return; - } - } - - childFrame->loader()->loadURL(url, referer, String(), false, FrameLoadTypeRedirectWithLockedBackForwardList, 0, 0); -} - -#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 - -ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn) -{ - String mimeType = mimeTypeIn; - // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure - if (mimeType.isEmpty()) - mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().substring(url.path().reverseFind('.') + 1)); - - if (mimeType.isEmpty()) - return ObjectContentFrame; // Go ahead and hope that we can display the content. - - if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) - return WebCore::ObjectContentImage; - -#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL - if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) - return WebCore::ObjectContentNetscapePlugin; -#endif - - if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) - return WebCore::ObjectContentFrame; - - return WebCore::ObjectContentNone; -} - -String FrameLoader::outgoingReferrer() const -{ - return m_outgoingReferrer; -} - -String FrameLoader::outgoingOrigin() const -{ - return m_frame->document()->securityOrigin()->toString(); -} - -bool FrameLoader::isMixedContent(SecurityOrigin* context, const KURL& url) -{ - if (context->protocol() != "https") - return false; // We only care about HTTPS security origins. - - if (!url.isValid() || SchemeRegistry::shouldTreatURLSchemeAsSecure(url.protocol())) - return false; // Loading these protocols is secure. - - return true; -} - -void FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL& url) -{ - if (!isMixedContent(context, url)) - return; - - String message = makeString("The page at ", m_URL.string(), " displayed insecure content from ", url.string(), ".\n"); - m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String()); - - m_client->didDisplayInsecureContent(); -} - -void FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& url) -{ - if (!isMixedContent(context, url)) - return; - - String message = makeString("The page at ", m_URL.string(), " ran insecure content from ", url.string(), ".\n"); - m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String()); - - m_client->didRunInsecureContent(context); -} - -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()); - } -} - -// FIXME: This does not belong in FrameLoader! -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 - if (m_stateMachine.firstLayoutDone()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); - m_frame->navigationScheduler()->cancel(true); - m_client->provisionalLoadStarted(); -} - -bool FrameLoader::isProcessingUserGesture() -{ - Frame* frame = m_frame->tree()->top(); - if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript)) - return true; // If JavaScript is disabled, a user gesture must have initiated the navigation. - return ScriptController::processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture. -} - -void FrameLoader::resetMultipleFormSubmissionProtection() -{ - m_submittedFormURL = KURL(); -} - -void FrameLoader::willSetEncoding() -{ - if (!m_workingURL.isEmpty()) - receivedFirstData(); -} - -#if ENABLE(WML) -static inline bool frameContainsWMLContent(Frame* frame) -{ - Document* document = frame ? frame->document() : 0; - if (!document) - return false; - - return document->containsWMLContent() || document->isWMLDocument(); -} -#endif - -void FrameLoader::updateFirstPartyForCookies() -{ - if (m_frame->tree()->parent()) - setFirstPartyForCookies(m_frame->tree()->parent()->document()->firstPartyForCookies()); - else - setFirstPartyForCookies(m_URL); -} - -void FrameLoader::setFirstPartyForCookies(const KURL& url) -{ - m_frame->document()->setFirstPartyForCookies(url); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->setFirstPartyForCookies(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::loadInSameDocument(const KURL& url, SerializedScriptValue* stateObject, bool isNewNavigation) -{ - // If we have a state object, we cannot also be a new navigation. - ASSERT(!stateObject || (stateObject && !isNewNavigation)); - - // Update the data source's request with the new URL to fake the URL change - m_frame->document()->setURL(url); - documentLoader()->replaceRequestURLForSameDocumentNavigation(url); - if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) { - // NB: must happen after replaceRequestURLForSameDocumentNavigation(), 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. - - history()->updateBackForwardListForFragmentScroll(); - } - - String oldURL; - bool hashChange = equalIgnoringFragmentIdentifier(url, m_URL) && url.fragmentIdentifier() != m_URL.fragmentIdentifier(); - oldURL = m_URL; - - m_URL = url; - history()->updateForSameDocumentNavigation(); - - // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor - if (hashChange) - m_frame->eventHandler()->stopAutoscrollTimer(); - - // It's important to model this as a load that starts and immediately finishes. - // Otherwise, the parent frame may think we never finished loading. - started(); - - // We need to scroll to the fragment whether or not a hash change occurred, since - // the user might have scrolled since the previous navigation. - if (FrameView* view = m_frame->view()) - view->scrollToFragment(m_URL); - - m_isComplete = false; - checkCompleted(); - - if (isNewNavigation) { - // 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->dispatchDidNavigateWithinPage(); - - m_frame->document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue()); - m_client->dispatchDidPopStateWithinPage(); - - if (hashChange) { - m_frame->document()->enqueueHashchangeEvent(oldURL, url); - m_client->dispatchDidChangeLocationWithinPage(); - } - - // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error - m_client->didFinishLoad(); -} - -bool FrameLoader::isComplete() const -{ - return m_isComplete; -} - -void FrameLoader::completed() -{ - RefPtr<Frame> protect(m_frame); - - for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame)) - descendant->navigationScheduler()->startTimer(); - - if (Frame* parent = m_frame->tree()->parent()) - parent->loader()->checkCompleted(); - - if (m_frame->view()) - m_frame->view()->maintainScrollPositionAtAnchor(0); -} - -void FrameLoader::started() -{ - for (Frame* frame = m_frame; frame; frame = frame->tree()->parent()) - frame->loader()->m_isComplete = false; -} - -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); -} - -// This is a hack to allow keep navigation to http/https feeds working. To remove this -// we need to introduce new API akin to registerURLSchemeAsLocal, that registers a -// protocols navigation policy. -static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url) -{ - const String& urlString = url.string(); - if (!urlString.startsWith("feed", false)) - return false; - - return urlString.startsWith("feed://", false) - || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false) - || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false) - || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false); -} - -void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList, - PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy) -{ - KURL url = request.resourceRequest().url(); - - ASSERT(m_frame->document()); - // FIXME: Should we move the isFeedWithNestedProtocolInHTTPFamily logic inside SecurityOrigin::canDisplay? - if (!isFeedWithNestedProtocolInHTTPFamily(url) && !request.requester()->canDisplay(url)) { - reportLocalLoadFailed(m_frame, url.string()); - return; - } - - String referrer; - String argsReferrer = request.resourceRequest().httpReferrer(); - if (!argsReferrer.isEmpty()) - referrer = argsReferrer; - else - referrer = m_outgoingReferrer; - - if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer) - referrer = String(); - - FrameLoadType loadType; - if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData) - loadType = FrameLoadTypeReload; - else if (lockBackForwardList) - loadType = FrameLoadTypeRedirectWithLockedBackForwardList; - else - loadType = FrameLoadTypeStandard; - - if (request.resourceRequest().httpMethod() == "POST") - loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get()); - else - loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.get()); - - // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual - // load if frame names have changed. - Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame; - Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.frameName()); - if (targetFrame && targetFrame != sourceFrame) { - if (Page* page = targetFrame->page()) - page->chrome()->focus(); - } -} - -void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType, - PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState) -{ - RefPtr<FormState> formState = prpFormState; - bool isFormSubmission = formState; - - ResourceRequest request(newURL); - if (!referrer.isEmpty()) { - request.setHTTPReferrer(referrer); - RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer); - addHTTPOriginIfNeeded(request, referrerOrigin->toString()); - } - addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission); - if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin) - request.setCachePolicy(ReloadIgnoringCacheData); - - ASSERT(newLoadType != FrameLoadTypeSame); - - // The search for a target frame is done earlier in the case of form submission. - Frame* targetFrame = isFormSubmission ? 0 : findFrameForNavigation(frameName); - if (targetFrame && targetFrame != m_frame) { - targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState.release()); - return; - } - - if (m_pageDismissalEventBeingDispatched) - return; - - NavigationAction action(newURL, newLoadType, isFormSubmission, event); - - if (!targetFrame && !frameName.isEmpty()) { - policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, - request, formState.release(), frameName, this); - 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); - policyChecker()->stopCheck(); - policyChecker()->setLoadType(newLoadType); - policyChecker()->checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(), - 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, lockHistory, newLoadType, formState.release()); - if (isRedirect) { - m_quickRedirectComing = false; - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->setIsClientRedirect(true); - } else if (sameURL) - // 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, bool lockHistory) -{ - load(request, SubstituteData(), lockHistory); -} - -void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory) -{ - 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; - RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData); - if (lockHistory && m_documentLoader) - loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory()); - load(loader.get()); -} - -void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory) -{ - if (frameName.isEmpty()) { - load(request, lockHistory); - return; - } - - Frame* frame = findFrameForNavigation(frameName); - if (frame) { - frame->loader()->load(request, lockHistory); - return; - } - - policyChecker()->checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), FrameLoader::callContinueLoadAfterNewWindowPolicy, request, 0, frameName, this); -} - -void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState) -{ - RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData()); - if (lockHistory && m_documentLoader) - loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory()); - - 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(); - addExtraFieldsToMainResourceRequest(r); - 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) -{ - // Retain because dispatchBeforeLoadEvent may release the last reference to it. - RefPtr<Frame> protect(m_frame); - - 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()); - - if (m_pageDismissalEventBeingDispatched) - return; - - policyChecker()->setLoadType(type); - RefPtr<FormState> formState = prpFormState; - bool isFormSubmission = formState; - - const KURL& newURL = loader->request().url(); - - if (shouldScrollToAnchor(isFormSubmission, policyChecker()->loadType(), newURL)) { - RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader; - NavigationAction action(newURL, policyChecker()->loadType(), isFormSubmission); - - oldDocumentLoader->setTriggeringAction(action); - policyChecker()->stopCheck(); - policyChecker()->checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState, - callContinueFragmentScrollAfterNavigationPolicy, this); - } else { - if (Frame* parent = m_frame->tree()->parent()) - loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding()); - - policyChecker()->stopCheck(); - setPolicyDocumentLoader(loader); - if (loader->triggeringAction().isEmpty()) - loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission)); - - if (Element* ownerElement = m_frame->document()->ownerElement()) { - if (!ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) { - continueLoadAfterNavigationPolicy(loader->request(), formState, false); - return; - } - } - - policyChecker()->checkNavigationPolicy(loader->request(), loader, formState, - callContinueLoadAfterNavigationPolicy, this); - } -} - -void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url) -{ - ASSERT(!url.isEmpty()); - if (!frame) - return; - - frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String()); -} - -const ResourceRequest& FrameLoader::initialRequest() const -{ - return activeDocumentLoader()->originalRequest(); -} - -bool FrameLoader::willLoadMediaElementURL(KURL& url) -{ - ResourceRequest request(url); - - unsigned long identifier; - ResourceError error; - requestFromDelegate(request, identifier, error); - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error); - - url = request.url(); - - return error.isNull(); -} - -bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader) -{ - KURL unreachableURL = docLoader->unreachableURL(); - - if (unreachableURL.isEmpty()) - return false; - - if (!isBackForwardLoadType(policyChecker()->loadType())) - 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 (policyChecker()->delegateIsDecidingNavigationPolicy() || policyChecker()->delegateIsHandlingUnimplementablePolicy()) - compareDocumentLoader = m_policyDocumentLoader.get(); - else if (m_delegateIsHandlingProvisionalLoadError) - compareDocumentLoader = m_provisionalDocumentLoader.get(); - - return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url(); -} - -void FrameLoader::reloadWithOverrideEncoding(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(), FrameLoadTypeReload, 0); -} - -void FrameLoader::reload(bool endToEndReload) -{ - if (!m_documentLoader) - return; - - // 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 (m_documentLoader->request().url().isEmpty()) - return; - - ResourceRequest initialRequest = m_documentLoader->request(); - - // Replace error-page URL with the URL we were trying to reach. - KURL unreachableURL = m_documentLoader->unreachableURL(); - if (!unreachableURL.isEmpty()) - initialRequest.setURL(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(); - - // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment. - request.setCachePolicy(ReloadIgnoringCacheData); - - // 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(), endToEndReload ? FrameLoadTypeReloadFromOrigin : 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; - - const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal(); - 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; - - // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false. - if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal()) - 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 or it is the opener of - // the target frame. - - 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 (!isDocumentSandboxed(m_frame, SandboxTopNavigation) && targetFrame == m_frame->tree()->top()) - return true; - - // A sandboxed frame can only navigate itself and its descendants. - if (isDocumentSandboxed(m_frame, SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame)) - return false; - - // Let a frame navigate its opener if the opener is a top-level window. - if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame) - 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 = makeString("Unsafe JavaScript attempt to initiate a navigation change for frame with URL ", - targetDocument->url().string(), " from frame with URL ", activeDocument->url().string(), ".\n"); - - // FIXME: should we print to the console of the activeFrame as well? - targetFrame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, 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(DatabasePolicy databasePolicy) -{ - ASSERT(!m_frame->document() || !m_frame->document()->inPageCache()); - if (m_pageDismissalEventBeingDispatched) - return; - - // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. - if (m_inStopAllLoaders) - return; - - m_inStopAllLoaders = true; - - policyChecker()->stopCheck(); - - stopLoadingSubframes(); - if (m_provisionalDocumentLoader) - m_provisionalDocumentLoader->stopLoading(databasePolicy); - if (m_documentLoader) - m_documentLoader->stopLoading(databasePolicy); - - setProvisionalDocumentLoader(0); - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (m_documentLoader) - m_documentLoader->clearArchiveResources(); -#endif - - m_checkTimer.stop(); - - 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_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument()); -} - -void FrameLoader::transferLoadingResourcesFromPage(Page* oldPage) -{ - ASSERT(oldPage != m_frame->page()); - if (isLoading()) { - activeDocumentLoader()->transferLoadingResourcesFromPage(oldPage); - oldPage->progress()->progressCompleted(m_frame); - if (m_frame->page()) - m_frame->page()->progress()->progressStarted(m_frame); - } -} - -void FrameLoader::dispatchTransferLoadingResourceFromPage(unsigned long identifier, DocumentLoader* docLoader, const ResourceRequest& request, Page* oldPage) -{ - notifier()->dispatchTransferLoadingResourceFromPage(identifier, docLoader, request, oldPage); -} - -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; -} - -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; -} - -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; -} - -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() -{ - RefPtr<CachedPage> cachedPage = m_loadingFromCachedPage ? pageCache()->get(history()->provisionalItem()) : 0; - RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader; - - LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame->tree()->uniqueName().string().utf8().data(), m_URL.string().utf8().data(), - pdl ? pdl->url().string().utf8().data() : "<no provisional DocumentLoader>"); - - // 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. - HistoryItem* item = history()->currentItem(); - if (!m_frame->tree()->parent() && PageCache::canCache(m_frame->page()) && !item->isInPageCache()) - pageCache()->add(item, m_frame->page()); - - if (m_loadType != FrameLoadTypeReplace) - closeOldDataSources(); - - if (!cachedPage && !m_stateMachine.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()) { - prepareForCachedPageRestore(); - cachedPage->restore(m_frame->page()); - - dispatchDidCommitLoad(); - - // If we have a title let the WebView know about it. - String title = m_documentLoader->title(); - if (!title.isNull()) - m_client->dispatchDidReceiveTitle(title); - - checkCompleted(); - } 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); - } - - LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->uniqueName().string().utf8().data(), m_URL.string().utf8().data()); - - if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect()) - history()->updateForClientRedirect(); - - if (m_loadingFromCachedPage) { - m_frame->document()->documentDidBecomeActive(); - - // Force a layout to update view size and thereby update scrollbars. - m_frame->view()->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. - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), error); - } - - pageCache()->remove(history()->currentItem()); - - m_documentLoader->setPrimaryLoadComplete(true); - - // FIXME: Why only this frame and not parent frames? - checkLoadCompleteForThisFrame(); - } -} - -void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) -{ - ASSERT(m_client->hasWebView()); - ASSERT(m_state == FrameStateProvisional); - - if (m_state != FrameStateProvisional) - return; - - m_client->setCopiesOnScroll(); - history()->updateForCommit(); - - // 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(); - - switch (m_loadType) { - case FrameLoadTypeForward: - case FrameLoadTypeBack: - case FrameLoadTypeBackWMLDeckNotAccessible: - case FrameLoadTypeIndexedBackForward: - if (m_frame->page()) { - // If the first load within a frame is a navigation within a back/forward list that was attached - // without any of the items being loaded then we need to update the history in a similar manner as - // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>). - if (!m_stateMachine.committedFirstRealDocumentLoad()) - history()->updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList); - - history()->updateForBackForwardNavigation(); - - // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object - if (history()->currentItem() && !cachedPage) - m_pendingStateObject = history()->currentItem()->stateObject(); - - // 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->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame()); - - } else - m_client->transitionToCommittedForNewPage(); - } - break; - - case FrameLoadTypeReload: - case FrameLoadTypeReloadFromOrigin: - case FrameLoadTypeSame: - case FrameLoadTypeReplace: - history()->updateForReload(); - m_client->transitionToCommittedForNewPage(); - break; - - case FrameLoadTypeStandard: - history()->updateForStandardLoad(); -#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 FrameLoadTypeRedirectWithLockedBackForwardList: - history()->updateForRedirectWithLockedBackForwardList(); - 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(); - } - - writer()->setMIMEType(dl->responseMIMEType()); - - // Tell the client we've committed this URL. - ASSERT(m_frame->view()); - - if (m_stateMachine.creatingInitialEmptyDocument()) - return; - - if (!m_stateMachine.committedFirstRealDocumentLoad()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit); - - if (!m_client->hasHTMLView()) - receivedFirstData(); -} - -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 lockBackForwardList) -{ - 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, we set a special mode so we treat the next - // load as part of the original 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. - // Loads triggered by JavaScript form submissions never count as quick redirects. - m_quickRedirectComing = (lockBackForwardList || history()->currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction; -} - -bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL) -{ -#if ENABLE(WML) - // All WML decks are supposed to be reloaded, even within the same URL fragment - if (frameContainsWMLContent(m_frame)) - return true; -#endif - - // 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.hasFragmentIdentifier()) - return true; - return !equalIgnoringFragmentIdentifier(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::prepareForCachedPageRestore() -{ - ASSERT(!m_frame->tree()->parent()); - ASSERT(m_frame->page()); - ASSERT(m_frame->page()->mainFrame() == m_frame); - - m_frame->navigationScheduler()->cancel(); - - // We still have to close the previous part page. - closeURL(); - - // Delete old status bar messages (if it _was_ activated on last URL). - if (m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) { - if (DOMWindow* window = m_frame->existingDOMWindow()) { - window->setStatus(String()); - window->setDefaultStatus(String()); - } - } -} - -void FrameLoader::open(CachedFrameBase& cachedFrame) -{ - m_isComplete = false; - - // Don't re-emit the load event. - m_didCallImplicitClose = true; - - KURL url = cachedFrame.url(); - - if (url.protocolInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty()) - url.setPath("/"); - - m_URL = url; - m_workingURL = url; - - started(); - clear(true, true, cachedFrame.isMainFrame()); - - Document* document = cachedFrame.document(); - ASSERT(document); - document->setInPageCache(false); - - m_needsClear = true; - m_isComplete = false; - m_didCallImplicitClose = false; - m_outgoingReferrer = url.string(); - - FrameView* view = cachedFrame.view(); - - // When navigating to a CachedFrame its FrameView should never be null. If it is we'll crash in creative ways downstream. - ASSERT(view); - view->setWasScrolledByUser(false); - - // Use the current ScrollView's frame rect. - if (m_frame->view()) - view->setFrameRect(m_frame->view()->frameRect()); - m_frame->setView(view); - - m_frame->setDocument(document); - m_frame->setDOMWindow(cachedFrame.domWindow()); - m_frame->domWindow()->setURL(document->url()); - m_frame->domWindow()->setSecurityOrigin(document->securityOrigin()); - - writer()->setDecoder(document->decoder()); - - updateFirstPartyForCookies(); - - cachedFrame.restore(); -} - -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::didReceiveServerRedirectForProvisionalLoadForFrame() -{ - m_client->dispatchDidReceiveServerRedirectForProvisionalLoad(); -} - -void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) -{ - // FIXME: Platforms shouldn't differ here! -#if PLATFORM(WIN) || PLATFORM(CHROMIUM) || defined(ANDROID) - if (m_stateMachine.creatingInitialEmptyDocument()) - return; -#endif - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - - // Give archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0. - RefPtr<Archive> archive = ArchiveFactory::create(loader->mainResourceData().get(), loader->responseMIMEType()); - if (!archive) { - m_client->finishedLoading(loader); - return; - } - - // FIXME: The remainder of this function should be moved to DocumentLoader. - - loader->addAllArchiveResources(archive.get()); - - ArchiveResource* mainResource = archive->mainResource(); - loader->setParsedArchiveData(mainResource->data()); - - writer()->setMIMEType(mainResource->mimeType()); - - closeURL(); - didOpenURL(mainResource->url()); - - ASSERT(m_frame->document()); - String userChosenEncoding = documentLoader()->overrideEncoding(); - bool encodingIsUserChosen = !userChosenEncoding.isNull(); - writer()->setEncoding(encodingIsUserChosen ? userChosenEncoding : mainResource->textEncoding(), encodingIsUserChosen); - writer()->addData(mainResource->data()->data(), mainResource->data()->size()); -#else - m_client->finishedLoading(loader); -#endif // ARCHIVE -} - -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; - documentLoader = childLoader->policyDocumentLoader(); - if (documentLoader) - return true; - } - return false; -} - -void FrameLoader::willChangeTitle(DocumentLoader* loader) -{ - m_client->willChangeTitle(loader); -} - -FrameLoadType FrameLoader::loadType() const -{ - return m_loadType; -} - -CachePolicy FrameLoader::subresourceCachePolicy() const -{ - if (m_isComplete) - return CachePolicyVerify; - - if (m_loadType == FrameLoadTypeReloadFromOrigin) - return CachePolicyReload; - - if (Frame* parentFrame = m_frame->tree()->parent()) { - CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy(); - if (parentCachePolicy != CachePolicyVerify) - return parentCachePolicy; - } - - // FIXME: POST documents are always Reloads, but their subresources should still be Revalidate. - // If we bring the CachePolicy.h and ResourceRequest cache policy enums in sync with each other and - // remember "Revalidate" in ResourceRequests, we can remove this "POST" check and return either "Reload" - // or "Revalidate" if the DocumentLoader was requested with either. - const ResourceRequest& request(documentLoader()->request()); - if (request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post")) - return CachePolicyRevalidate; - - if (m_loadType == FrameLoadTypeReload) - return CachePolicyRevalidate; - - if (request.cachePolicy() == ReturnCacheDataElseLoad) - return CachePolicyHistoryBuffer; - - return CachePolicyVerify; -} - -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 = history()->currentItem(); - - bool shouldReset = true; - if (!(pdl->isLoadingInAPISense() && !pdl->isStopping())) { - 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(); - - // If we're in the middle of loading multipart data, we need to restore the document loader. - if (isReplacing() && !m_documentLoader.get()) - setDocumentLoader(m_provisionalDocumentLoader.get()); - - // 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 (activeDocumentLoader()) { - KURL unreachableURL = activeDocumentLoader()->unreachableURL(); - if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url()) - shouldReset = false; - } - } - if (shouldReset && item) - if (Page* page = m_frame->page()) { - page->backForward()->setCurrentItem(item.get()); - Settings* settings = m_frame->settings(); - page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : item.get()); - } - return; - } - - case FrameStateCommittedPage: { - DocumentLoader* dl = m_documentLoader.get(); - if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping())) - 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 (m_frame->page()) { - if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) - history()->restoreScrollPositionAndViewState(); - } - - if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad()) - return; - - const ResourceError& error = dl->mainDocumentError(); - 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() && m_frame->document()->renderArena()) - android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(), - m_frame->document()->renderArena()->reportPoolSize()); -#endif - return; - } - - case FrameStateComplete: - frameLoadCompleted(); - return; - } - - ASSERT_NOT_REACHED(); -} - -void FrameLoader::continueLoadAfterWillSubmitForm() -{ - 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_loadingFromCachedPage = false; - - unsigned long identifier = 0; - - if (Page* page = m_frame->page()) { - identifier = page->progress()->createUniqueIdentifier(); - notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest()); - } - - ASSERT(!m_provisionalDocumentLoader->timing()->navigationStart); - m_provisionalDocumentLoader->timing()->navigationStart = currentTime(); - - if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier)) - m_provisionalDocumentLoader->updateLoading(); -} - -void FrameLoader::didFirstLayout() -{ - if (m_frame->page() && isBackForwardLoadType(m_loadType)) - history()->restoreScrollPositionAndViewState(); - - if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone); - m_client->dispatchDidFirstLayout(); -} - -void FrameLoader::didFirstVisuallyNonEmptyLayout() -{ - m_client->dispatchDidFirstVisuallyNonEmptyLayout(); -} - -void FrameLoader::frameLoadCompleted() -{ - // Note: Can be called multiple times. - - m_client->frameLoadCompleted(); - - history()->updateForFrameLoadCompleted(); - - // After a canceled provisional load, firstLayoutDone is false. - // Reset it to true if we're displaying a page. - if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone()) - m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone); -} - -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::closeAndRemoveChild(Frame* child) -{ - child->tree()->detachFromParent(); - - child->setView(0); - if (child->ownerElement() && child->page()) - child->page()->decrementFrameCount(); - // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed(). - child->pageDestroyed(); - - m_frame->tree()->removeChild(child); -} - -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()); - - m_shouldCallCheckLoadComplete = false; - - // 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; -} - -String FrameLoader::userAgent(const KURL& url) const -{ - return m_client->userAgent(url); -} - -void FrameLoader::handledOnloadEvents() -{ - m_client->dispatchDidHandleOnloadEvents(); - - if (documentLoader()) { - documentLoader()->handledOnloadEvents(); -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - documentLoader()->applicationCacheHost()->stopDeferringEvents(); -#endif - } -} - -void FrameLoader::frameDetached() -{ - stopAllLoaders(); - m_frame->document()->stopActiveDOMObjects(); - detachFromParent(); -} - -void FrameLoader::detachFromParent() -{ - RefPtr<Frame> protect(m_frame); - - closeURL(); - history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); - detachChildren(); - // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren() - // will trigger the unload event handlers of any child frames, and those event - // handlers might start a new subresource load in this frame. - stopAllLoaders(); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->frameDetachedFromParent(m_frame); -#endif - - detachViewsAndDocumentLoader(); - - if (Frame* parent = m_frame->tree()->parent()) { - parent->loader()->closeAndRemoveChild(m_frame); - parent->loader()->scheduleCheckCompleted(); - } else { - m_frame->setView(0); - // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed(). - m_frame->pageDestroyed(); - } -} - -void FrameLoader::detachViewsAndDocumentLoader() -{ - m_client->detachedFromParent2(); - setDocumentLoader(0); - m_client->detachedFromParent3(); -} - -void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request) -{ - addExtraFieldsToRequest(request, m_loadType, false, false); -} - -void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request) -{ - addExtraFieldsToRequest(request, m_loadType, true, false); -} - -void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest) -{ - // Don't set the cookie policy URL if it's already been set. - // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>). - if (request.firstPartyForCookies().isEmpty()) { - if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest)) - request.setFirstPartyForCookies(request.url()); - else if (Document* document = m_frame->document()) - request.setFirstPartyForCookies(document->firstPartyForCookies()); - } - - // The remaining modifications are only necessary for HTTP and HTTPS. - if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily()) - return; - - applyUserAgent(request); - - // If we inherit cache policy from a main resource, we use the DocumentLoader's - // original request 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 (!mainResource) { - if (request.isConditional()) - request.setCachePolicy(ReloadIgnoringCacheData); - else if (documentLoader()->isLoadingInAPISense()) - request.setCachePolicy(documentLoader()->originalRequest().cachePolicy()); - else - request.setCachePolicy(UseProtocolCachePolicy); - } else if (loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadFromOrigin || request.isConditional()) - request.setCachePolicy(ReloadIgnoringCacheData); - else if (isBackForwardLoadType(loadType) && m_stateMachine.committedFirstRealDocumentLoad() && !request.url().protocolIs("https")) - request.setCachePolicy(ReturnCacheDataElseLoad); - - if (request.cachePolicy() == ReloadIgnoringCacheData) { - if (loadType == FrameLoadTypeReload) - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - else if (loadType == FrameLoadTypeReloadFromOrigin) { - request.setHTTPHeaderField("Cache-Control", "no-cache"); - request.setHTTPHeaderField("Pragma", "no-cache"); - } - } - - if (mainResource) - request.setHTTPAccept(defaultAcceptHeader); - - // Make sure we send the Origin header. - addHTTPOriginIfNeeded(request, String()); - - // Always try UTF-8. If that fails, try frame encoding (if any) and then the default. - // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1. - Settings* settings = m_frame->settings(); - request.setResponseContentDispositionEncodingFallbackArray("UTF-8", writer()->deprecatedFrameEncoding(), settings ? settings->defaultTextEncodingName() : 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::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState) -{ - 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); - - if (!referrer.isEmpty()) - workingResourceRequest.setHTTPReferrer(referrer); - workingResourceRequest.setHTTPOrigin(origin); - workingResourceRequest.setHTTPMethod("POST"); - workingResourceRequest.setHTTPBody(formData); - workingResourceRequest.setHTTPContentType(contentType); - addExtraFieldsToRequest(workingResourceRequest, loadType, true, true); - - NavigationAction action(url, loadType, true, event); - - if (!frameName.isEmpty()) { - // The search for a target frame is done earlier in the case of form submission. - if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName)) - targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release()); - else - policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, workingResourceRequest, formState.release(), frameName, this); - } else - loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release()); -} - -unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data) -{ - String referrer = m_outgoingReferrer; - if (SecurityOrigin::shouldHideReferrer(request.url(), referrer)) - referrer = String(); - - ResourceRequest initialRequest = request; - initialRequest.setTimeoutInterval(10); - - if (!referrer.isEmpty()) - initialRequest.setHTTPReferrer(referrer); - addHTTPOriginIfNeeded(initialRequest, outgoingOrigin()); - - if (Page* page = m_frame->page()) - initialRequest.setFirstPartyForCookies(page->mainFrame()->loader()->documentLoader()->request().url()); - initialRequest.setHTTPUserAgent(client()->userAgent(request.url())); - - addExtraFieldsToSubresourceRequest(initialRequest); - - unsigned long identifier = 0; - ResourceRequest newRequest(initialRequest); - requestFromDelegate(newRequest, identifier, error); - - if (error.isNull()) { - ASSERT(!newRequest.isNull()); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) { -#endif - ResourceHandle::loadResourceSynchronously(networkingContext(), newRequest, storedCredentials, error, response, data); -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data); - } -#endif - } - - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), error); - return identifier; -} - -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) { - if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url()) - m_submittedFormURL = KURL(); - - // 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. - history()->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) -{ - m_quickRedirectComing = false; - - if (!shouldContinue) - return; - - bool isRedirect = m_quickRedirectComing || policyChecker()->loadType() == FrameLoadTypeRedirectWithLockedBackForwardList; - loadInSameDocument(request.url(), 0, !isRedirect); -} - -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 != FrameLoadTypeReloadFromOrigin - && 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->document()->isFrameSet(); -} - -void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument, - const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue) -{ - FrameLoader* loader = static_cast<FrameLoader*>(argument); - loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue); -} - -bool FrameLoader::shouldClose() -{ - Page* page = m_frame->page(); - Chrome* chrome = page ? page->chrome() : 0; - if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel()) - return true; - - DOMWindow* domWindow = m_frame->existingDOMWindow(); - if (!domWindow) - return true; - - RefPtr<Document> document = m_frame->document(); - HTMLElement* body = document->body(); - if (!body) - return true; - - RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); - m_pageDismissalEventBeingDispatched = true; - domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document()); - m_pageDismissalEventBeingDispatched = false; - - if (!beforeUnloadEvent->defaultPrevented()) - document->defaultEventHandler(beforeUnloadEvent.get()); - if (beforeUnloadEvent->result().isNull()) - return true; - - String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->result()); - return chrome->runBeforeUnloadConfirmPanel(text, m_frame); -} - -void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, 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 = history()->provisionalItem() ? history()->provisionalItem()->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() || 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(policyChecker()->loadType())) - if (Page* page = m_frame->page()) { - Frame* mainFrame = page->mainFrame(); - if (HistoryItem* resetItem = mainFrame->loader()->history()->currentItem()) { - page->backForward()->setCurrentItem(resetItem); - Settings* settings = m_frame->settings(); - page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem); - } - } - return; - } - - FrameLoadType type = policyChecker()->loadType(); - 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; - -#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) && USE(JSC) - if (Page* page = m_frame->page()) { - if (page->mainFrame() == m_frame) - page->inspectorController()->resume(); - } -#endif - - setProvisionalDocumentLoader(m_policyDocumentLoader.get()); - m_loadType = type; - setState(FrameStateProvisional); - - setPolicyDocumentLoader(0); - - if (isBackForwardLoadType(type) && history()->provisionalItem()->isInPageCache()) { - loadProvisionalItemFromCachedPage(); - return; - } - - if (formState) - m_client->dispatchWillSubmitForm(&PolicyChecker::continueLoadAfterWillSubmitForm, formState); - else - continueLoadAfterWillSubmitForm(); -} - -void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument, - const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) -{ - FrameLoader* loader = static_cast<FrameLoader*>(argument); - loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue); -} - -void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request, - PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) -{ - if (!shouldContinue) - return; - - RefPtr<Frame> frame = m_frame; - RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(action); - if (!mainFrame) - return; - - if (frameName != "_blank") - mainFrame->tree()->setName(frameName); - - mainFrame->page()->setOpenedByDOM(); - mainFrame->loader()->m_client->dispatchShow(); - if (!m_suppressOpenerInNewFrame) - mainFrame->loader()->setOpener(frame.get()); - mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState); -} - -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(); - notifier()->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request); - } - - ResourceRequest newRequest(request); - notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse()); - - if (newRequest.isNull()) - error = cancelledError(request); - else - error = ResourceError(); - - request = newRequest; -} - -void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource) -{ - Page* page = m_frame->page(); - if (!page) - return; - - if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url())) - return; - - if (!page->areMemoryCacheClientCallsEnabled()) { -#if ENABLE(INSPECTOR) - page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource); -#endif - m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url()); - m_documentLoader->didTellClientAboutLoad(resource->url()); - return; - } - - ResourceRequest request(resource->url()); - if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) { -#if ENABLE(INSPECTOR) - page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource); -#endif - m_documentLoader->didTellClientAboutLoad(resource->url()); - return; - } - - unsigned long identifier; - ResourceError error; - requestFromDelegate(request, identifier, error); -#if ENABLE(INSPECTOR) - page->inspectorController()->markResourceAsCached(identifier); -#endif - notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), error); -} - -void FrameLoader::applyUserAgent(ResourceRequest& request) -{ - String userAgent = client()->userAgent(request.url()); - ASSERT(!userAgent.isNull()); - request.setHTTPUserAgent(userAgent); -} - -bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url) -{ - Frame* topFrame = m_frame->tree()->top(); - if (m_frame == topFrame) - return false; - - if (equalIgnoringCase(content, "deny")) - return true; - - if (equalIgnoringCase(content, "sameorigin")) { - RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url); - if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin())) - return true; - } - - return false; -} - -void FrameLoader::loadProvisionalItemFromCachedPage() -{ - DocumentLoader* provisionalLoader = provisionalDocumentLoader(); - LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().string().utf8().data()); - - provisionalLoader->prepareForLoadStart(); - - m_loadingFromCachedPage = true; - - // Should have timing data from previous time(s) the page was shown. - ASSERT(provisionalLoader->timing()->navigationStart); - provisionalLoader->resetTiming(); - provisionalLoader->timing()->navigationStart = currentTime(); - - provisionalLoader->setCommitted(true); - commitProvisionalLoad(); -} - -bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const -{ - if (!history()->currentItem()) - return false; - return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL(); -} - -void FrameLoader::checkDidPerformFirstNavigation() -{ - Page* page = m_frame->page(); - if (!page) - return; - - if (!m_didPerformFirstNavigation && page->backForward()->currentItem() && !page->backForward()->backItem() && !page->backForward()->forwardItem()) { - m_didPerformFirstNavigation = true; - m_client->didPerformFirstNavigation(); - } -} - -Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) -{ - Frame* frame = m_frame->tree()->find(name); - if (!shouldAllowNavigation(frame)) - return 0; - return frame; -} - -void FrameLoader::loadSameDocumentItem(HistoryItem* item) -{ - ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber()); - - // Save user view state to the current history item here since we don't do a normal load. - // FIXME: Does form state need to be saved here too? - history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); - if (FrameView* view = m_frame->view()) - view->setWasScrolledByUser(false); - - history()->setCurrentItem(item); - - // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load - loadInSameDocument(item->url(), item->stateObject(), false); - - // Restore user view state from the current history item here since we don't do a normal load. - history()->restoreScrollPositionAndViewState(); -} - -// FIXME: This function should really be split into a couple pieces, some of -// which should be methods of HistoryController and some of which should be -// methods of FrameLoader. -void FrameLoader::loadDifferentDocumentItem(HistoryItem* item, FrameLoadType loadType) -{ - // Remember this item so we can traverse any child items as child frames load - history()->setProvisionalItem(item); - - if (CachedPage* cachedPage = pageCache()->get(item)) { - loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0); - return; - } - - KURL itemURL = item->url(); - KURL itemOriginalURL = item->originalURL(); - KURL currentURL; - if (documentLoader()) - currentURL = documentLoader()->url(); - RefPtr<FormData> formData = item->formData(); - - bool addedExtraFields = false; - ResourceRequest request(itemURL); - - if (!item->referrer().isNull()) - request.setHTTPReferrer(item->referrer()); - - // 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->document()); - - request.setHTTPMethod("POST"); - request.setHTTPBody(formData); - request.setHTTPContentType(item->formContentType()); - RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer()); - addHTTPOriginIfNeeded(request, securityOrigin->toString()); - - // Make sure to add extra fields to the request after the Origin header is added for the FormData case. - // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion. - addExtraFieldsToRequest(request, m_loadType, true, formData); - addedExtraFields = true; - - // 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, m_frame)) - action = NavigationAction(itemURL, loadType, false); - else { - request.setCachePolicy(ReloadIgnoringCacheData); - action = NavigationAction(itemURL, NavigationTypeFormResubmitted); - } - } else { - switch (loadType) { - case FrameLoadTypeReload: - case FrameLoadTypeReloadFromOrigin: - request.setCachePolicy(ReloadIgnoringCacheData); - break; - case FrameLoadTypeBack: - case FrameLoadTypeBackWMLDeckNotAccessible: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - // If the first load within a frame is a navigation within a back/forward list that was attached - // without any of the items being loaded then we should use the default caching policy (<rdar://problem/8131355>). - if (m_stateMachine.committedFirstRealDocumentLoad() && !itemURL.protocolIs("https")) - request.setCachePolicy(ReturnCacheDataElseLoad); - break; - case FrameLoadTypeStandard: - case FrameLoadTypeRedirectWithLockedBackForwardList: - break; - case FrameLoadTypeSame: - default: - ASSERT_NOT_REACHED(); - } - - action = NavigationAction(itemOriginalURL, loadType, false); - } - - if (!addedExtraFields) - addExtraFieldsToRequest(request, m_loadType, true, formData); - - loadWithNavigationAction(request, action, false, loadType, 0); -} - -// Loads content into this frame, as specified by history item -void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) -{ - HistoryItem* currentItem = history()->currentItem(); - bool sameDocumentNavigation = currentItem && item->shouldDoSameDocumentNavigationTo(currentItem); - -#if ENABLE(WML) - // All WML decks should go through the real load mechanism, not the scroll-to-anchor code - // FIXME: Why do WML decks have this different behavior? - // Are WML decks incompatible with HTML5 pushState/replaceState which require inter-document history navigations? - // Should this new API be disabled for WML pages, or does WML need to update their mechanism to act like normal loads? - // If scroll-to-anchor navigations were broken for WML and required them to have different loading behavior, then - // state object loads are certainly also broken for them. - if (frameContainsWMLContent(m_frame)) - sameDocumentNavigation = false; -#endif - - if (sameDocumentNavigation) - loadSameDocumentItem(item); - else - loadDifferentDocumentItem(item, loadType); -} - -void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error) -{ - m_client->setMainDocumentError(loader, error); -} - -void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError&) -{ - 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::interruptionForPolicyChangeError(const ResourceRequest& request) const -{ - return m_client->interruptForPolicyChangeError(request); -} - -ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const -{ - return m_client->fileDoesNotExistError(response); -} - -bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader) -{ - return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier()); -} - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -bool FrameLoader::canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace) -{ - return m_client->canAuthenticateAgainstProtectionSpace(loader->documentLoader(), loader->identifier(), protectionSpace); -} -#endif - -void FrameLoader::setTitle(const String& title) -{ - documentLoader()->setTitle(title); -} - -void FrameLoader::setIconURL(const String& iconURL) -{ - documentLoader()->setIconURL(iconURL); -} - -KURL FrameLoader::originalRequestURL() const -{ - return activeDocumentLoader()->originalRequest().url(); -} - -String FrameLoader::referrer() const -{ - return m_documentLoader ? m_documentLoader->request().httpReferrer() : ""; -} - -void FrameLoader::dispatchDocumentElementAvailable() -{ - m_frame->injectUserScripts(InjectAtDocumentStart); - m_client->documentElementAvailable(); -} - -void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() -{ - if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) - return; - - Vector<DOMWrapperWorld*> worlds; - ScriptController::getAllWorlds(worlds); - for (size_t i = 0; i < worlds.size(); ++i) - dispatchDidClearWindowObjectInWorld(worlds[i]); -} - -void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) -{ - if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script()->existingWindowShell(world)) - return; - - m_client->dispatchDidClearWindowObjectInWorld(world); - -#if ENABLE(INSPECTOR) - if (world != mainThreadNormalWorld()) - return; - - if (Page* page = m_frame->page()) { - if (InspectorController* inspector = page->inspectorController()) - inspector->inspectedWindowScriptObjectCleared(m_frame); - } -#endif -} - -void FrameLoader::updateSandboxFlags() -{ - SandboxFlags flags = m_forcedSandboxFlags; - if (Frame* parentFrame = m_frame->tree()->parent()) - flags |= parentFrame->loader()->sandboxFlags(); - if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement()) - flags |= ownerElement->sandboxFlags(); - - if (m_sandboxFlags == flags) - return; - - m_sandboxFlags = flags; - - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->loader()->updateSandboxFlags(); -} - -void FrameLoader::didChangeTitle(DocumentLoader* loader) -{ - m_client->didChangeTitle(loader); - - if (loader == m_documentLoader) { - // Must update the entries in the back-forward list too. - history()->setCurrentItemTitle(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::didChangeIcons(DocumentLoader* loader) -{ - if (loader == m_documentLoader) - m_client->dispatchDidChangeIcons(); -} - -void FrameLoader::dispatchDidCommitLoad() -{ - if (m_stateMachine.creatingInitialEmptyDocument()) - return; - - m_client->dispatchDidCommitLoad(); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didCommitLoad(m_documentLoader.get()); -#endif -} - -void FrameLoader::tellClientAboutPastMemoryCacheLoads() -{ - ASSERT(m_frame->page()); - ASSERT(m_frame->page()->areMemoryCacheClientCallsEnabled()); - - if (!m_documentLoader) - return; - - Vector<String> pastLoads; - m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads); - - size_t size = pastLoads.size(); - for (size_t i = 0; i < size; ++i) { - CachedResource* resource = cache()->resourceForURL(KURL(ParsedURLString, pastLoads[i])); - - // FIXME: These loads, loaded from cache, but now gone from the cache by the time - // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client. - // Consider if there's some efficient way of remembering enough to deliver this client call. - // We have the URL, but not the rest of the response or the length. - if (!resource) - continue; - - ResourceRequest request(resource->url()); - m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize()); - } -} - -NetworkingContext* FrameLoader::networkingContext() const -{ - return m_networkingContext.get(); -} - -bool FrameLoaderClient::hasHTMLView() const -{ - return true; -} - -Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, bool& created) -{ - ASSERT(!features.dialog || request.frameName().isEmpty()); - - if (!request.frameName().isEmpty() && request.frameName() != "_blank") { - Frame* frame = lookupFrame->tree()->find(request.frameName()); - if (frame && openerFrame->loader()->shouldAllowNavigation(frame)) { - if (!request.resourceRequest().url().isEmpty()) - frame->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer); - if (Page* page = frame->page()) - page->chrome()->focus(); - created = false; - return frame; - } - } - - // Sandboxed frames cannot open new auxiliary browsing contexts. - if (isDocumentSandboxed(openerFrame, SandboxNavigation)) - return 0; - - // FIXME: Setting the referrer should be the caller's responsibility. - FrameLoadRequest requestWithReferrer = request; - requestWithReferrer.resourceRequest().setHTTPReferrer(openerFrame->loader()->outgoingReferrer()); - FrameLoader::addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), openerFrame->loader()->outgoingOrigin()); - - Page* oldPage = openerFrame->page(); - if (!oldPage) - return 0; - - NavigationAction action; - Page* page = oldPage->chrome()->createWindow(openerFrame, requestWithReferrer, features, action); - 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; -} - -} // namespace WebCore diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h deleted file mode 100644 index 9b2ea48..0000000 --- a/WebCore/loader/FrameLoader.h +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) Research In Motion Limited 2009. 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 "CachePolicy.h" -#include "DocumentWriter.h" -#include "FrameLoaderStateMachine.h" -#include "FrameLoaderTypes.h" -#include "HistoryController.h" -#include "NavigationScheduler.h" -#include "PolicyCallback.h" -#include "PolicyChecker.h" -#include "ResourceLoadNotifier.h" -#include "ResourceRequest.h" -#include "SubframeLoader.h" -#include "ThreadableLoader.h" -#include "Timer.h" -#include <wtf/Forward.h> - -namespace WebCore { - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size -class Archive; -#endif -class AuthenticationChallenge; -class CachedFrameBase; -class CachedPage; -class CachedResource; -class DOMWrapperWorld; -class Document; -class DocumentLoader; -class Event; -class FormData; -class FormState; -class FormSubmission; -class Frame; -class FrameLoaderClient; -class FrameNetworkingContext; -class HistoryItem; -class HTMLFormElement; -class IconLoader; -class NavigationAction; -class NetworkingContext; -class Page; -class ProtectionSpace; -class ResourceError; -class ResourceLoader; -class ResourceResponse; -class ScriptSourceCode; -class ScriptValue; -class SecurityOrigin; -class SerializedScriptValue; -class SharedBuffer; -class SubstituteData; -class TextResourceDecoder; - -struct FrameLoadRequest; -struct WindowFeatures; - -bool isBackForwardLoadType(FrameLoadType); - -class FrameLoader : public Noncopyable { -public: - FrameLoader(Frame*, FrameLoaderClient*); - ~FrameLoader(); - - void init(); - - Frame* frame() const { return m_frame; } - - PolicyChecker* policyChecker() const { return &m_policyChecker; } - HistoryController* history() const { return &m_history; } - ResourceLoadNotifier* notifier() const { return &m_notifer; } - DocumentWriter* writer() const { return &m_writer; } - SubframeLoader* subframeLoader() const { return &m_subframeLoader; } - - // FIXME: This is not cool, people. There are too many different functions that all start loads. - // We should aim to consolidate these into a smaller set of functions, and try to reuse more of - // the logic by extracting common code paths. - - void prepareForLoadStart(); - void setupForReplace(); - void setupForReplaceByMIMEType(const String& newMIMEType); - - void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*); - - void loadFrameRequest(const FrameLoadRequest&, bool lockHistory, bool lockBackForwardList, // Called by submitForm, calls loadPostRequest and loadURL. - PassRefPtr<Event>, PassRefPtr<FormState>, ReferrerPolicy); - - void load(const ResourceRequest&, bool lockHistory); // Called by WebFrame, calls load(ResourceRequest, SubstituteData). - void load(const ResourceRequest&, const SubstituteData&, bool lockHistory); // Called both by WebFrame and internally, calls load(DocumentLoader*). - void load(const ResourceRequest&, const String& frameName, bool lockHistory); // Called by WebPluginController. - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - void loadArchive(PassRefPtr<Archive>); -#endif - - static void reportLocalLoadFailed(Frame*, const String& url); - - unsigned long loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data); - - bool canHandleRequest(const ResourceRequest&); - - // Also not cool. - void stopAllLoaders(DatabasePolicy = DatabasePolicyStop); - void stopForUserCancel(bool deferCheckLoadComplete = false); - - bool isLoadingMainResource() const { return m_isLoadingMainResource; } - bool isLoading() const; - bool frameHasLoaded() const; - void transferLoadingResourcesFromPage(Page*); - void dispatchTransferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*); - - int numPendingOrLoadingRequests(bool recurse) const; - String referrer() const; - String outgoingReferrer() const; - String outgoingOrigin() const; - - DocumentLoader* activeDocumentLoader() const; - DocumentLoader* documentLoader() const { return m_documentLoader.get(); } - DocumentLoader* policyDocumentLoader() const { return m_policyDocumentLoader.get(); } - DocumentLoader* provisionalDocumentLoader() const { return m_provisionalDocumentLoader.get(); } - FrameState state() const { return m_state; } - static double timeOfLastCompletedLoad(); - - bool shouldUseCredentialStorage(ResourceLoader*); -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - bool canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace); -#endif - const ResourceRequest& originalRequest() const; - const ResourceRequest& initialRequest() const; - void receivedMainResourceError(const ResourceError&, bool isComplete); - - bool willLoadMediaElementURL(KURL&); - - 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; - ResourceError interruptionForPolicyChangeError(const ResourceRequest&) const; - - bool isHostedByObjectElement() const; - bool isLoadingMainFrame() const; - bool canShowMIMEType(const String& MIMEType) const; - bool representationExistsForURLScheme(const String& URLScheme); - String generatedMIMETypeForURLScheme(const String& URLScheme); - - void reload(bool endToEndReload = false); - void reloadWithOverrideEncoding(const String& overrideEncoding); - - void didReceiveServerRedirectForProvisionalLoadForFrame(); - void finishedLoadingDocument(DocumentLoader*); - 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*); - void didChangeIcons(DocumentLoader*); - - FrameLoadType loadType() const; - - CachePolicy subresourceCachePolicy() const; - - void didFirstLayout(); - - void didFirstVisuallyNonEmptyLayout(); - - void loadedResourceFromMemoryCache(const CachedResource*); - void tellClientAboutPastMemoryCacheLoads(); - - void checkLoadComplete(); - void detachFromParent(); - void detachViewsAndDocumentLoader(); - - void addExtraFieldsToSubresourceRequest(ResourceRequest&); - void addExtraFieldsToMainResourceRequest(ResourceRequest&); - - static void addHTTPOriginIfNeeded(ResourceRequest&, String origin); - - FrameLoaderClient* client() const { return m_client; } - - void setDefersLoading(bool); - - void changeLocation(PassRefPtr<SecurityOrigin>, const KURL&, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool refresh = false); - void urlSelected(const KURL&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, ReferrerPolicy); - - void submitForm(PassRefPtr<FormSubmission>); - - void stop(); - void stopLoading(UnloadEventPolicy, DatabasePolicy = DatabasePolicyStop); - bool closeURL(); - - void didExplicitOpen(); - - // Callbacks from DocumentWriter - void didBeginDocument(bool dispatchWindowObjectAvailable); - void didEndDocument(); - void willSetEncoding(); - - KURL iconURL(); - void commitIconURLToIconDatabase(const KURL&); - - KURL baseURL() const; - - void handledOnloadEvents(); - String userAgent(const KURL&) const; - - void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*); - void dispatchDidClearWindowObjectsInAllWorlds(); - void dispatchDocumentElementAvailable(); - - void ownerElementSandboxFlagsChanged() { updateSandboxFlags(); } - - bool isSandboxed(SandboxFlags mask) const { return m_sandboxFlags & mask; } - SandboxFlags sandboxFlags() const { return m_sandboxFlags; } - // The following sandbox flags will be forced, regardless of changes to - // the sandbox attribute of any parent frames. - void setForcedSandboxFlags(SandboxFlags flags) { m_forcedSandboxFlags = flags; m_sandboxFlags |= flags; } - - // Mixed content related functions. - static bool isMixedContent(SecurityOrigin* context, const KURL&); - void checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL&); - void checkIfRunInsecureContent(SecurityOrigin* context, const KURL&); - - Frame* opener(); - void setOpener(Frame*); - - bool isProcessingUserGesture(); - - void resetMultipleFormSubmissionProtection(); - - void checkCallImplicitClose(); - - void frameDetached(); - - const KURL& url() const { return m_URL; } - - // setURL is a low-level setter and does not trigger loading. - void setURL(const KURL&); - - void loadDone(); - void finishedParsing(); - void checkCompleted(); - - void checkDidPerformFirstNavigation(); - - bool isComplete() const; - - KURL completeURL(const String& url); - - void cancelAndClear(); - - void setTitle(const String&); - void setIconURL(const String&); - - void commitProvisionalLoad(); - bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } - - FrameLoaderStateMachine* stateMachine() const { return &m_stateMachine; } - - void iconLoadDecisionAvailable(); - - bool shouldAllowNavigation(Frame* targetFrame) const; - Frame* findFrameForNavigation(const AtomicString& name); - - void startIconLoader(); - - void applyUserAgent(ResourceRequest& request); - - bool shouldInterruptLoadForXFrameOptions(const String&, const KURL&); - - void open(CachedFrameBase&); - - // FIXME: Should these really be public? - void completed(); - bool allAncestorsAreComplete() const; // including this - bool allChildrenAreComplete() const; // immediate children, not all descendants - void clientRedirected(const KURL&, double delay, double fireDate, bool lockBackForwardList); - void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress); - void loadItem(HistoryItem*, FrameLoadType); - - // FIXME: This is public because this asynchronous callback from the FrameLoaderClient - // uses the policy machinery (and therefore is called via the PolicyChecker). Once we - // introduce a proper callback type for this function, we should make it private again. - void continueLoadAfterWillSubmitForm(); - - bool suppressOpenerInNewFrame() const { return m_suppressOpenerInNewFrame; } - - static ObjectContentType defaultObjectContentType(const KURL& url, const String& mimeType); - - void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true); - - bool quickRedirectComing() const { return m_quickRedirectComing; } - - bool shouldClose(); - - void started(); - - bool pageDismissalEventBeingDispatched() const { return m_pageDismissalEventBeingDispatched; } - - NetworkingContext* networkingContext() const; - -private: - void checkTimerFired(Timer<FrameLoader>*); - - void loadSameDocumentItem(HistoryItem*); - void loadDifferentDocumentItem(HistoryItem*, FrameLoadType); - - void loadProvisionalItemFromCachedPage(); - - void receivedFirstData(); - - void updateFirstPartyForCookies(); - void setFirstPartyForCookies(const KURL&); - - void addExtraFieldsToRequest(ResourceRequest&, FrameLoadType loadType, bool isMainResource, bool cookiePolicyURLFromRequest); - - // Also not cool. - void stopLoadingSubframes(); - - void clearProvisionalLoad(); - void markLoadComplete(); - void transitionToCommitted(PassRefPtr<CachedPage>); - void frameLoadCompleted(); - - void mainReceivedError(const ResourceError&, bool isComplete); - - static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue); - static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - - void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue); - void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); - - bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType, const KURL&); - - void checkLoadCompleteForThisFrame(); - - void setDocumentLoader(DocumentLoader*); - void setPolicyDocumentLoader(DocumentLoader*); - void setProvisionalDocumentLoader(DocumentLoader*); - - void setState(FrameState); - - void closeOldDataSources(); - void prepareForCachedPageRestore(); - - bool shouldReloadToHandleUnreachableURL(DocumentLoader*); - - void dispatchDidCommitLoad(); - - void urlSelected(const FrameLoadRequest&, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, ReferrerPolicy, ShouldReplaceDocumentIfJavaScriptURL); - - void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy - void load(DocumentLoader*); // Calls loadWithDocumentLoader - - void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, // Calls loadWithDocumentLoader - bool lockHistory, FrameLoadType, PassRefPtr<FormState>); - - void loadPostRequest(const ResourceRequest&, const String& referrer, // Called by loadFrameRequest, calls loadWithNavigationAction - const String& frameName, bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>); - void loadURL(const KURL&, const String& referrer, const String& frameName, // Called by loadFrameRequest, calls loadWithNavigationAction or dispatches to navigation policy delegate - bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>); - - bool shouldReload(const KURL& currentURL, const KURL& destinationURL); - - void requestFromDelegate(ResourceRequest&, unsigned long& identifier, ResourceError&); - - void recursiveCheckLoadComplete(); - - void detachChildren(); - void closeAndRemoveChild(Frame*); - - void loadInSameDocument(const KURL&, SerializedScriptValue* stateObject, bool isNewNavigation); - - void provisionalLoadStarted(); - - bool didOpenURL(const KURL&); - - void scheduleCheckCompleted(); - void scheduleCheckLoadComplete(); - void startCheckCompleteTimer(); - - KURL originalRequestURL() const; - - bool shouldTreatURLAsSameAsCurrent(const KURL&) const; - - void updateSandboxFlags(); - - Frame* m_frame; - FrameLoaderClient* m_client; - - mutable PolicyChecker m_policyChecker; - mutable HistoryController m_history; - mutable ResourceLoadNotifier m_notifer; - mutable DocumentWriter m_writer; - mutable SubframeLoader m_subframeLoader; - mutable FrameLoaderStateMachine m_stateMachine; - - 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; - - bool m_delegateIsHandlingProvisionalLoadError; - - bool m_quickRedirectComing; - bool m_sentRedirectNotification; - bool m_inStopAllLoaders; - - String m_outgoingReferrer; - - bool m_isExecutingJavaScriptFormAction; - - bool m_didCallImplicitClose; - bool m_wasUnloadEventEmitted; - bool m_pageDismissalEventBeingDispatched; - bool m_isComplete; - bool m_isLoadingMainResource; - - RefPtr<SerializedScriptValue> m_pendingStateObject; - - KURL m_URL; - KURL m_workingURL; - - OwnPtr<IconLoader> m_iconLoader; - bool m_mayLoadIconLater; - - bool m_needsClear; - - KURL m_submittedFormURL; - - Timer<FrameLoader> m_checkTimer; - bool m_shouldCallCheckCompleted; - bool m_shouldCallCheckLoadComplete; - - Frame* m_opener; - HashSet<Frame*> m_openedFrames; - - bool m_didPerformFirstNavigation; - bool m_loadingFromCachedPage; - bool m_suppressOpenerInNewFrame; - - SandboxFlags m_sandboxFlags; - SandboxFlags m_forcedSandboxFlags; - - RefPtr<FrameNetworkingContext> m_networkingContext; -}; - -// This function is called by createWindow() in JSDOMWindowBase.cpp, for example, for -// modal dialog creation. The lookupFrame is for looking up the frame name in case -// the frame name references a frame different from the openerFrame, e.g. when it is -// "_self" or "_parent". -// -// FIXME: Consider making this function part of an appropriate class (not FrameLoader) -// and moving it to a more appropriate location. -Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest&, const WindowFeatures&, bool& created); - -} // namespace WebCore - -#endif // FrameLoader_h diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h deleted file mode 100644 index 7348293..0000000 --- a/WebCore/loader/FrameLoaderClient.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 "ScrollTypes.h" -#include <wtf/Forward.h> -#include <wtf/Vector.h> - -typedef class _jobject* jobject; - -#if PLATFORM(MAC) && !defined(__OBJC__) -class NSCachedURLResponse; -class NSView; -#endif - -namespace WebCore { - - class AuthenticationChallenge; - class CachedFrame; - class Color; - class DOMWrapperWorld; - class DocumentLoader; - class Element; - class FormState; - class Frame; - class FrameLoader; - class FrameNetworkingContext; - class HistoryItem; - class HTMLAppletElement; - class HTMLFormElement; - class HTMLFrameOwnerElement; -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - class HTMLMediaElement; -#endif - class HTMLPlugInElement; - class IntSize; - class KURL; - class NavigationAction; - class Page; - class ProtectionSpace; - class PluginView; - class PolicyChecker; - class ResourceError; - class ResourceHandle; - class ResourceLoader; - class ResourceRequest; - class ResourceResponse; - class SecurityOrigin; - class SharedBuffer; - class SubstituteData; - class Widget; - - typedef void (PolicyChecker::*FramePolicyFunction)(PolicyAction); - - class FrameLoaderClient { - public: - // An inline function cannot be the first non-abstract virtual function declared - // in the class as it results in the vtable being generated as a weak symbol. - // This hurts performance (in Mac OS X at least, when loadig frameworks), so we - // don't want to do it in WebKit. - virtual bool hasHTMLView() const; - - virtual ~FrameLoaderClient() { } - - virtual void frameLoaderDestroyed() = 0; - - virtual bool hasWebView() const = 0; // mainly for assertions - - 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 bool shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier) = 0; - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) = 0; -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - virtual bool canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long identifier, const ProtectionSpace&) = 0; -#endif - 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 dispatchDidNavigateWithinPage() { } - virtual void dispatchDidChangeLocationWithinPage() = 0; - virtual void dispatchDidPushStateWithinPage() = 0; - virtual void dispatchDidReplaceStateWithinPage() = 0; - virtual void dispatchDidPopStateWithinPage() = 0; - virtual void dispatchWillClose() = 0; - virtual void dispatchDidReceiveIcon() = 0; - virtual void dispatchDidStartProvisionalLoad() = 0; - virtual void dispatchDidReceiveTitle(const String& title) = 0; - virtual void dispatchDidChangeIcons() = 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 void dispatchDidFirstVisuallyNonEmptyLayout() = 0; - - virtual Frame* dispatchCreatePage(const NavigationAction&) = 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 dispatchWillSendSubmitEvent(HTMLFormElement*) = 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() = 0; - virtual void updateGlobalHistoryRedirectLinks() = 0; - - virtual bool shouldGoToHistoryItem(HistoryItem*) const = 0; - virtual void dispatchDidAddBackForwardItem(HistoryItem*) const = 0; - virtual void dispatchDidRemoveBackForwardItem(HistoryItem*) const = 0; - virtual void dispatchDidChangeBackForwardIndex() const = 0; - - // This frame has displayed inactive content (such as an image) from an - // insecure source. Inactive content cannot spread to other frames. - virtual void didDisplayInsecureContent() = 0; - - // The indicated security origin has run active content (such as a - // script) from an insecure source. Note that the insecure content can - // spread to other frames in the same origin. - virtual void didRunInsecureContent(SecurityOrigin*) = 0; - - 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 canShowMIMETypeAsHTML(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 savePlatformDataToCachedFrame(CachedFrame*) = 0; - virtual void transitionToCommittedFromCachedFrame(CachedFrame*) = 0; - virtual void transitionToCommittedForNewPage() = 0; - - virtual void dispatchDidBecomeFrameset(bool) = 0; // Can change due to navigation or DOM modification. - - 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 void didTransferChildFrameToNewDocument(Page* oldPage) = 0; - virtual void transferLoadingResourceFromPage(unsigned long identifier, DocumentLoader*, const ResourceRequest&, Page* oldPage) = 0; - virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0; - virtual void redirectDataToPlugin(Widget* pluginWidget) = 0; - - virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) = 0; - - virtual void dispatchDidFailToStartPlugin(const PluginView*) const { } -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - virtual PassRefPtr<Widget> createMediaPlayerProxyPlugin(const IntSize&, HTMLMediaElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&) = 0; - virtual void hideMediaPlayerProxyPlugin(Widget*) = 0; - virtual void showMediaPlayerProxyPlugin(Widget*) = 0; -#endif - - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) = 0; - virtual String overrideMediaType() const = 0; - - virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*) = 0; - virtual void documentElementAvailable() = 0; - virtual void didPerformFirstNavigation() const = 0; // "Navigation" here means a transition from one page to another that ends up in the back/forward list. - -#if USE(V8) - virtual void didCreateScriptContextForFrame() = 0; - virtual void didDestroyScriptContextForFrame() = 0; - virtual void didCreateIsolatedScriptContext() = 0; - virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) = 0; -#endif - - virtual void registerForIconNotification(bool listen = true) = 0; -#ifdef ANDROID_APPLE_TOUCH_ICON - virtual void dispatchDidReceiveTouchIconURL(const String& url, bool precomposed) = 0; -#endif - -#if PLATFORM(MAC) -#if ENABLE(JAVA_BRIDGE) - virtual jobject javaApplet(NSView*) { return 0; } -#endif - virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse*) const = 0; -#endif -#if USE(CFNETWORK) - virtual bool shouldCacheResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&, const unsigned char* data, unsigned long long length) = 0; -#endif - - virtual bool shouldUsePluginDocument(const String& /*mimeType*/) const { return false; } - virtual bool shouldLoadMediaElementURL(const KURL&) const { return true; } - - virtual void didChangeScrollOffset() { } - - virtual bool allowJavaScript(bool enabledPerSettings) { return enabledPerSettings; } - virtual bool allowPlugins(bool enabledPerSettings) { return enabledPerSettings; } - virtual bool allowImages(bool enabledPerSettings) { return enabledPerSettings; } - - // This callback notifies the client that the frame was about to run - // JavaScript but did not because allowJavaScript returned false. We - // have a separate callback here because there are a number of places - // that need to know if JavaScript is enabled but are not necessarily - // preparing to execute script. - virtual void didNotAllowScript() { } - // This callback is similar, but for plugins. - virtual void didNotAllowPlugins() { } - - virtual PassRefPtr<FrameNetworkingContext> createNetworkingContext() = 0; - }; - -} // namespace WebCore - -#endif // FrameLoaderClient_h diff --git a/WebCore/loader/FrameLoaderStateMachine.cpp b/WebCore/loader/FrameLoaderStateMachine.cpp deleted file mode 100644 index 790b144..0000000 --- a/WebCore/loader/FrameLoaderStateMachine.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2010 Google 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 Google, Inc. 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 THE COPYRIGHT HOLDERS AND 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 "FrameLoaderStateMachine.h" - -#include <wtf/Assertions.h> - -namespace WebCore { - - -FrameLoaderStateMachine::FrameLoaderStateMachine() - : m_state(Uninitialized) -{ -} - -bool FrameLoaderStateMachine::committingFirstRealLoad() const -{ - return m_state == DisplayingInitialEmptyDocument; -} - -bool FrameLoaderStateMachine::committedFirstRealDocumentLoad() const -{ - return m_state >= DisplayingInitialEmptyDocumentPostCommit; -} - -bool FrameLoaderStateMachine::creatingInitialEmptyDocument() const -{ - return m_state == CreatingInitialEmptyDocument; -} - -bool FrameLoaderStateMachine::isDisplayingInitialEmptyDocument() const -{ - return m_state == DisplayingInitialEmptyDocument || m_state == DisplayingInitialEmptyDocumentPostCommit; -} - -bool FrameLoaderStateMachine::firstLayoutDone() const -{ - return m_state == FirstLayoutDone; -} - -void FrameLoaderStateMachine::advanceTo(State state) -{ - ASSERT(State(m_state + 1) == state || (firstLayoutDone() && state == CommittedFirstRealLoad)); - m_state = state; -} - -} // namespace WebCore diff --git a/WebCore/loader/FrameLoaderStateMachine.h b/WebCore/loader/FrameLoaderStateMachine.h deleted file mode 100644 index c3408c2..0000000 --- a/WebCore/loader/FrameLoaderStateMachine.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2010 Google 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 Google, Inc. 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 THE COPYRIGHT HOLDERS AND 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 FrameLoaderStateMachine_h -#define FrameLoaderStateMachine_h - -#include <wtf/Noncopyable.h> - -namespace WebCore { - -// Encapsulates a state machine for FrameLoader. Note that this is different from FrameState, -// which stores the state of the current load that FrameLoader is executing. -class FrameLoaderStateMachine : public Noncopyable { -public: - FrameLoaderStateMachine(); - - // Once a load has been committed, the state may - // alternate between CommittedFirstRealLoad and FirstLayoutDone. - // Otherwise, the states only go down the list. - enum State { - Uninitialized, - CreatingInitialEmptyDocument, - DisplayingInitialEmptyDocument, - DisplayingInitialEmptyDocumentPostCommit, - CommittedFirstRealLoad, - FirstLayoutDone - }; - - bool committingFirstRealLoad() const; - bool committedFirstRealDocumentLoad() const; - bool creatingInitialEmptyDocument() const; - bool isDisplayingInitialEmptyDocument() const; - bool firstLayoutDone() const; - void advanceTo(State); - -private: - State m_state; -}; - -} // namespace WebCore - -#endif // FrameLoaderStateMachine_h diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h deleted file mode 100644 index 016de19..0000000 --- a/WebCore/loader/FrameLoaderTypes.h +++ /dev/null @@ -1,129 +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, - }; - - // NOTE: Keep in sync with WebKit/mac/WebView/WebFramePrivate.h and WebKit/win/Interfaces/IWebFramePrivate.idl - enum FrameLoadType { - FrameLoadTypeStandard, - FrameLoadTypeBack, - FrameLoadTypeForward, - FrameLoadTypeIndexedBackForward, // a multi-item hop in the backforward list - FrameLoadTypeReload, - // Skipped value: 'FrameLoadTypeReloadAllowingStaleData', still present in mac/win public API. Ready to be reused - FrameLoadTypeSame = FrameLoadTypeReload + 2, // user loads same URL again (but not reload button) - FrameLoadTypeRedirectWithLockedBackForwardList, // FIXME: Merge "lockBackForwardList", "lockHistory", "quickRedirect" and "clientRedirect" into a single concept of redirect. - FrameLoadTypeReplace, - FrameLoadTypeReloadFromOrigin, - FrameLoadTypeBackWMLDeckNotAccessible - }; - - enum NavigationType { - NavigationTypeLinkClicked, - NavigationTypeFormSubmitted, - NavigationTypeBackForward, - NavigationTypeReload, - NavigationTypeFormResubmitted, - NavigationTypeOther - }; - - enum DatabasePolicy { - DatabasePolicyStop, // The database thread should be stopped and database connections closed. - DatabasePolicyContinue - }; - - enum ObjectContentType { - ObjectContentNone, - ObjectContentImage, - ObjectContentFrame, - ObjectContentNetscapePlugin, - ObjectContentOtherPlugin - }; - - enum UnloadEventPolicy { - UnloadEventPolicyNone, - UnloadEventPolicyUnloadOnly, - UnloadEventPolicyUnloadAndPageHide - }; - - enum ReferrerPolicy { - SendReferrer, - NoReferrer - }; - - enum SandboxFlag { - SandboxNone = 0, - SandboxNavigation = 1, - SandboxPlugins = 1 << 1, - SandboxOrigin = 1 << 2, - SandboxForms = 1 << 3, - SandboxScripts = 1 << 4, - SandboxTopNavigation = 1 << 5, - SandboxAll = -1 // Mask with all bits set to 1. - }; - - enum SecurityCheckPolicy { - SkipSecurityCheck, - DoSecurityCheck - }; - - // Passed to FrameLoader::urlSelected() and ScriptController::executeIfJavaScriptURL() - // to control whether, in the case of a JavaScript URL, executeIfJavaScriptURL() should - // replace the document. It is a FIXME to eliminate this extra parameter from - // executeIfJavaScriptURL(), in which case this enum can go away. - enum ShouldReplaceDocumentIfJavaScriptURL { - ReplaceDocumentIfJavaScriptURL, - DoNotReplaceDocumentIfJavaScriptURL - }; - - enum ReasonForCallingAllowPlugins { - AboutToInstantiatePlugin, - NotAboutToInstantiatePlugin - }; - - typedef int SandboxFlags; -} - -#endif diff --git a/WebCore/loader/FrameNetworkingContext.h b/WebCore/loader/FrameNetworkingContext.h deleted file mode 100644 index dff1144..0000000 --- a/WebCore/loader/FrameNetworkingContext.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) - - 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 FrameNetworkingContext_h -#define FrameNetworkingContext_h - -#include "Frame.h" -#include "NetworkingContext.h" - -namespace WebCore { - -class FrameNetworkingContext : public NetworkingContext { -public: - void invalidate() - { - m_frame = 0; - } - -protected: - FrameNetworkingContext(Frame* frame) - : m_frame(frame) - { - } - - Frame* frame() const { return m_frame; } - -private: - virtual bool isValid() const { return m_frame; } - - Frame* m_frame; -}; - -} - -#endif // FrameNetworkingContext_h diff --git a/WebCore/loader/HistoryController.cpp b/WebCore/loader/HistoryController.cpp deleted file mode 100644 index ff733a9..0000000 --- a/WebCore/loader/HistoryController.cpp +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "HistoryController.h" - -#include "BackForwardController.h" -#include "CachedPage.h" -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "FrameLoaderStateMachine.h" -#include "FrameTree.h" -#include "FrameView.h" -#include "HistoryItem.h" -#include "Logging.h" -#include "Page.h" -#include "PageCache.h" -#include "PageGroup.h" -#include "Settings.h" -#include <wtf/text/CString.h> - -#if USE(PLATFORM_STRATEGIES) -#include "PlatformStrategies.h" -#include "VisitedLinkStrategy.h" -#endif - -namespace WebCore { - -static inline void addVisitedLink(Page* page, const KURL& url) -{ -#if USE(PLATFORM_STRATEGIES) - platformStrategies()->visitedLinkStrategy()->addVisitedLink(page, visitedLinkHash(url.string().characters(), url.string().length())); -#else - page->group().addVisitedLink(url); -#endif -} - -HistoryController::HistoryController(Frame* frame) - : m_frame(frame) - , m_frameLoadComplete(true) -{ -} - -HistoryController::~HistoryController() -{ -} - -void HistoryController::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_frame->loader()->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 HistoryController::restoreScrollPositionAndViewState() -{ - if (!m_frame->loader()->stateMachine()->committedFirstRealDocumentLoad()) - return; - - ASSERT(m_currentItem); - - // 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_currentItem) - 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_frame->loader()->client()->restoreViewState(); - - if (FrameView* view = m_frame->view()) - if (!view->wasScrolledByUser()) - view->setScrollPosition(m_currentItem->scrollPoint()); -} - -void HistoryController::updateBackForwardListForFragmentScroll() -{ - updateBackForwardListClippedAtTarget(false); -} - -void HistoryController::saveDocumentState() -{ - // FIXME: Reading this bit of FrameLoader state here is unfortunate. I need to study - // this more to see if we can remove this dependency. - if (m_frame->loader()->stateMachine()->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 we keep track of the end of a page transition with m_frameLoadComplete. We - // leverage the checkLoadComplete recursion to achieve this goal. - - HistoryItem* item = m_frameLoadComplete ? m_currentItem.get() : m_previousItem.get(); - if (!item) - return; - - Document* document = m_frame->document(); - ASSERT(document); - - if (item->isCurrentDocument(document)) { - LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->uniqueName().string().utf8().data(), item); - item->setDocumentState(document->formElementsState()); - } -} - -// Walk the frame tree, telling all frames to save their form state into their current -// history item. -void HistoryController::saveDocumentAndScrollState() -{ - for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) { - frame->loader()->history()->saveDocumentState(); - frame->loader()->history()->saveScrollPositionAndViewStateToItem(frame->loader()->history()->currentItem()); - } -} - -void HistoryController::restoreDocumentState() -{ - Document* doc = m_frame->document(); - - HistoryItem* itemToRestore = 0; - - switch (m_frame->loader()->loadType()) { - case FrameLoadTypeReload: - case FrameLoadTypeReloadFromOrigin: - case FrameLoadTypeSame: - case FrameLoadTypeReplace: - break; - case FrameLoadTypeBack: - case FrameLoadTypeBackWMLDeckNotAccessible: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - case FrameLoadTypeRedirectWithLockedBackForwardList: - case FrameLoadTypeStandard: - itemToRestore = m_currentItem.get(); - } - - if (!itemToRestore) - return; - - LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->uniqueName().string().utf8().data(), itemToRestore); - doc->setStateForNewFormElements(itemToRestore->documentState()); -} - -void HistoryController::invalidateCurrentItemCachedPage() -{ - // When we are pre-commit, the currentItem is where the pageCache data resides - CachedPage* cachedPage = pageCache()->get(currentItem()); - - // 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(currentItem()); -} - -// Main funnel for navigating to a previous location (back/forward, non-search snap-back) -// This includes recursion to handle loading into framesets properly -void HistoryController::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_frame->loader()->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 - HistoryItem* currentItem = page->backForward()->currentItem(); - page->backForward()->setCurrentItem(targetItem); - Settings* settings = m_frame->settings(); - page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : targetItem); - recursiveGoToItem(targetItem, currentItem, type); -} - -void HistoryController::updateForBackForwardNavigation() -{ -#if !LOG_DISABLED - if (m_frame->loader()->documentLoader()) - LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); -#endif - - // Must grab the current scroll position before disturbing it - if (!m_frameLoadComplete) - saveScrollPositionAndViewStateToItem(m_previousItem.get()); -} - -void HistoryController::updateForReload() -{ -#if !LOG_DISABLED - if (m_frame->loader()->documentLoader()) - LOG(History, "WebCoreHistory: Updating History for reload in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); -#endif - - if (m_currentItem) { - pageCache()->remove(m_currentItem.get()); - - if (m_frame->loader()->loadType() == FrameLoadTypeReload || m_frame->loader()->loadType() == FrameLoadTypeReloadFromOrigin) - saveScrollPositionAndViewStateToItem(m_currentItem.get()); - - // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072 - if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty()) - m_currentItem->setURL(m_frame->loader()->documentLoader()->requestURL()); - } -} - -// There are 3 things you might think of as "history", all of which are handled by these functions. -// -// 1) Back/forward: The m_currentItem is part of this mechanism. -// 2) Global history: Handled by the client. -// 3) Visited links: Handled by the PageGroup. - -void HistoryController::updateForStandardLoad(HistoryUpdateType updateType) -{ - LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", m_frame->loader()->documentLoader()->url().string().ascii().data()); - - FrameLoader* frameLoader = m_frame->loader(); - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = frameLoader->documentLoader()->urlForHistory(); - - if (!frameLoader->documentLoader()->isClientRedirect()) { - if (!historyURL.isEmpty()) { - if (updateType != UpdateAllExceptBackForwardList) - updateBackForwardListClippedAtTarget(true); - if (!needPrivacy) { - frameLoader->client()->updateGlobalHistory(); - frameLoader->documentLoader()->setDidCreateGlobalHistoryEntry(true); - if (frameLoader->documentLoader()->unreachableURL().isEmpty()) - frameLoader->client()->updateGlobalHistoryRedirectLinks(); - } - if (Page* page = m_frame->page()) - page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForward()->currentItem()); - } - } else if (frameLoader->documentLoader()->unreachableURL().isEmpty() && m_currentItem) { - m_currentItem->setURL(frameLoader->documentLoader()->url()); - m_currentItem->setFormInfoFromRequest(frameLoader->documentLoader()->request()); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - addVisitedLink(page, historyURL); - - if (!frameLoader->documentLoader()->didCreateGlobalHistoryEntry() && frameLoader->documentLoader()->unreachableURL().isEmpty() && !frameLoader->url().isEmpty()) - frameLoader->client()->updateGlobalHistoryRedirectLinks(); - } -} - -void HistoryController::updateForRedirectWithLockedBackForwardList() -{ -#if !LOG_DISABLED - if (m_frame->loader()->documentLoader()) - LOG(History, "WebCoreHistory: Updating History for redirect load in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); -#endif - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = m_frame->loader()->documentLoader()->urlForHistory(); - - if (m_frame->loader()->documentLoader()->isClientRedirect()) { - if (!m_currentItem && !m_frame->tree()->parent()) { - if (!historyURL.isEmpty()) { - updateBackForwardListClippedAtTarget(true); - if (!needPrivacy) { - m_frame->loader()->client()->updateGlobalHistory(); - m_frame->loader()->documentLoader()->setDidCreateGlobalHistoryEntry(true); - if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty()) - m_frame->loader()->client()->updateGlobalHistoryRedirectLinks(); - } - if (Page* page = m_frame->page()) - page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForward()->currentItem()); - } - } - if (m_currentItem) { - m_currentItem->setURL(m_frame->loader()->documentLoader()->url()); - m_currentItem->setFormInfoFromRequest(m_frame->loader()->documentLoader()->request()); - } - } else { - Frame* parentFrame = m_frame->tree()->parent(); - if (parentFrame && parentFrame->loader()->history()->m_currentItem) - parentFrame->loader()->history()->m_currentItem->setChildItem(createItem(true)); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - addVisitedLink(page, historyURL); - - if (!m_frame->loader()->documentLoader()->didCreateGlobalHistoryEntry() && m_frame->loader()->documentLoader()->unreachableURL().isEmpty() && !m_frame->loader()->url().isEmpty()) - m_frame->loader()->client()->updateGlobalHistoryRedirectLinks(); - } -} - -void HistoryController::updateForClientRedirect() -{ -#if !LOG_DISABLED - if (m_frame->loader()->documentLoader()) - LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", m_frame->loader()->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_currentItem) { - m_currentItem->clearDocumentState(); - m_currentItem->clearScrollPoint(); - } - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = m_frame->loader()->documentLoader()->urlForHistory(); - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - addVisitedLink(page, historyURL); - } -} - -void HistoryController::updateForCommit() -{ - FrameLoader* frameLoader = m_frame->loader(); -#if !LOG_DISABLED - if (frameLoader->documentLoader()) - LOG(History, "WebCoreHistory: Updating History for commit in frame %s", frameLoader->documentLoader()->title().utf8().data()); -#endif - FrameLoadType type = frameLoader->loadType(); - if (isBackForwardLoadType(type) || - ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !frameLoader->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_frameLoadComplete = false; - m_previousItem = m_currentItem; - ASSERT(m_provisionalItem); - m_currentItem = m_provisionalItem; - m_provisionalItem = 0; - } -} - -void HistoryController::updateForSameDocumentNavigation() -{ - if (m_frame->loader()->url().isEmpty()) - return; - - Settings* settings = m_frame->settings(); - if (!settings || settings->privateBrowsingEnabled()) - return; - - Page* page = m_frame->page(); - if (!page) - return; - - addVisitedLink(page, m_frame->loader()->url()); -} - -void HistoryController::updateForFrameLoadCompleted() -{ - // 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 track that - // the load is complete so that we use the current item instead. - m_frameLoadComplete = true; -} - -void HistoryController::setCurrentItem(HistoryItem* item) -{ - m_frameLoadComplete = false; - m_previousItem = m_currentItem; - m_currentItem = item; -} - -void HistoryController::setCurrentItemTitle(const String& title) -{ - if (m_currentItem) - m_currentItem->setTitle(title); -} - -bool HistoryController::currentItemShouldBeReplaced() const -{ - // From the HTML5 spec for location.assign(): - // "If the browsing context's session history contains only one Document, - // and that was the about:blank Document created when the browsing context - // was created, then the navigation must be done with replacement enabled." - return m_currentItem && !m_previousItem && equalIgnoringCase(m_currentItem->urlString(), blankURL()); -} - -void HistoryController::setProvisionalItem(HistoryItem* item) -{ - m_provisionalItem = item; -} - -PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal) -{ - DocumentLoader* documentLoader = m_frame->loader()->documentLoader(); - - KURL unreachableURL = documentLoader ? documentLoader->unreachableURL() : KURL(); - - KURL url; - KURL originalURL; - - if (!unreachableURL.isEmpty()) { - url = unreachableURL; - originalURL = unreachableURL; - } else { - originalURL = documentLoader ? documentLoader->originalURL() : KURL(); - if (useOriginal) - url = originalURL; - else if (documentLoader) - url = documentLoader->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()->uniqueName() : ""; - String title = documentLoader ? documentLoader->title() : ""; - - RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->uniqueName(), parent, title); - item->setOriginalURLString(originalURL.string()); - - if (!unreachableURL.isEmpty() || !documentLoader || documentLoader->response().httpStatusCode() >= 400) - item->setLastVisitWasFailure(true); - - // Save form state if this is a POST - if (documentLoader) { - if (useOriginal) - item->setFormInfoFromRequest(documentLoader->originalRequest()); - else - item->setFormInfoFromRequest(documentLoader->request()); - } - - // Set the item for which we will save document state - m_frameLoadComplete = false; - m_previousItem = m_currentItem; - m_currentItem = item; - - return item.release(); -} - -PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget) -{ - RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false); - if (!m_frameLoadComplete) - saveScrollPositionAndViewStateToItem(m_previousItem.get()); - - if (!clipAtTarget || m_frame != targetFrame) { - // save frame state for items that aren't loading (khtml doesn't save those) - saveDocumentState(); - - // clipAtTarget is false for navigations within the same document, so - // we should copy the documentSequenceNumber over to the newly create - // item. Non-target items are just clones, and they should therefore - // preserve the same itemSequenceNumber. - if (m_previousItem) { - if (m_frame != targetFrame) - bfItem->setItemSequenceNumber(m_previousItem->itemSequenceNumber()); - bfItem->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); - } - - 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->history()->createItemTree(targetFrame, clipAtTarget)); - } - } - // FIXME: Eliminate the isTargetItem flag in favor of itemSequenceNumber. - if (m_frame == targetFrame) - bfItem->setIsTargetItem(true); - return bfItem; -} - -// 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 HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) -{ - ASSERT(item); - ASSERT(fromItem); - - // If the item we're going to is a clone of the item we're at, then do - // not load it again, and continue history traversal to its children. - // The current frame tree and the frame tree snapshot in the item have - // to match. - // Note: If item and fromItem are the same, then we need to create a new - // document. - if (item != fromItem - && item->itemSequenceNumber() == fromItem->itemSequenceNumber() - && currentFramesMatchItem(item) - && fromItem->hasSameFrames(item)) - { - // This content is good, so leave it alone and look for children that need reloading - // Save form state (works from currentItem, since m_frameLoadComplete is true) - ASSERT(m_frameLoadComplete); - saveDocumentState(); - saveScrollPositionAndViewStateToItem(m_currentItem.get()); - - if (FrameView* view = m_frame->view()) - view->setWasScrolledByUser(false); - - m_previousItem = m_currentItem; - m_currentItem = 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 childFrameName = childItems[i]->target(); - HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFrameName); - ASSERT(fromChildItem); - Frame* childFrame = m_frame->tree()->child(childFrameName); - ASSERT(childFrame); - childFrame->loader()->history()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); - } - } else { - m_frame->loader()->loadItem(item, type); - } -} - -// Helper method that determines whether the current frame tree matches given history item's. -bool HistoryController::currentFramesMatchItem(HistoryItem* item) const -{ - if ((!m_frame->tree()->uniqueName().isEmpty() || !item->target().isEmpty()) && m_frame->tree()->uniqueName() != item->target()) - return false; - - 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; - } - - return true; -} - -void HistoryController::updateBackForwardListClippedAtTarget(bool doClip) -{ - // 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 function is called with doClip=true 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. - - Page* page = m_frame->page(); - if (!page) - return; - - if (m_frame->loader()->documentLoader()->urlForHistory().isEmpty()) - return; - - Frame* mainFrame = page->mainFrame(); - ASSERT(mainFrame); - FrameLoader* frameLoader = mainFrame->loader(); - - frameLoader->checkDidPerformFirstNavigation(); - - RefPtr<HistoryItem> topItem = frameLoader->history()->createItemTree(m_frame, doClip); - LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", topItem.get(), m_frame->loader()->documentLoader()->url().string().ascii().data()); - page->backForward()->addItem(topItem.release()); -} - -void HistoryController::pushState(PassRefPtr<SerializedScriptValue> stateObject, const String& title, const String& urlString) -{ - if (!m_currentItem) - return; - - Page* page = m_frame->page(); - ASSERT(page); - - // Get a HistoryItem tree for the current frame tree. - RefPtr<HistoryItem> topItem = page->mainFrame()->loader()->history()->createItemTree(m_frame, false); - - // Override data in the current item (created by createItemTree) to reflect - // the pushState() arguments. - m_currentItem->setTitle(title); - m_currentItem->setStateObject(stateObject); - m_currentItem->setURLString(urlString); - - page->backForward()->addItem(topItem.release()); -} - -void HistoryController::replaceState(PassRefPtr<SerializedScriptValue> stateObject, const String& title, const String& urlString) -{ - if (!m_currentItem) - return; - - if (!urlString.isEmpty()) - m_currentItem->setURLString(urlString); - m_currentItem->setTitle(title); - m_currentItem->setStateObject(stateObject); -} - -} // namespace WebCore diff --git a/WebCore/loader/HistoryController.h b/WebCore/loader/HistoryController.h deleted file mode 100644 index 1bf5072..0000000 --- a/WebCore/loader/HistoryController.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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. - */ - -#ifndef HistoryController_h -#define HistoryController_h - -#include "FrameLoaderTypes.h" -#include "PlatformString.h" -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; -class HistoryItem; -class SerializedScriptValue; - -class HistoryController : public Noncopyable { -public: - enum HistoryUpdateType { UpdateAll, UpdateAllExceptBackForwardList }; - - HistoryController(Frame*); - ~HistoryController(); - - void saveScrollPositionAndViewStateToItem(HistoryItem*); - void restoreScrollPositionAndViewState(); - - void updateBackForwardListForFragmentScroll(); - - void saveDocumentState(); - void saveDocumentAndScrollState(); - void restoreDocumentState(); - - void invalidateCurrentItemCachedPage(); - - void goToItem(HistoryItem*, FrameLoadType); - - void updateForBackForwardNavigation(); - void updateForReload(); - void updateForStandardLoad(HistoryUpdateType updateType = UpdateAll); - void updateForRedirectWithLockedBackForwardList(); - void updateForClientRedirect(); - void updateForCommit(); - void updateForSameDocumentNavigation(); - void updateForFrameLoadCompleted(); - - HistoryItem* currentItem() const { return m_currentItem.get(); } - void setCurrentItem(HistoryItem*); - void setCurrentItemTitle(const String&); - bool currentItemShouldBeReplaced() const; - - HistoryItem* previousItem() const { return m_previousItem.get(); } - - HistoryItem* provisionalItem() const { return m_provisionalItem.get(); } - void setProvisionalItem(HistoryItem*); - - void pushState(PassRefPtr<SerializedScriptValue>, const String& title, const String& url); - void replaceState(PassRefPtr<SerializedScriptValue>, const String& title, const String& url); - -private: - PassRefPtr<HistoryItem> createItem(bool useOriginal); - PassRefPtr<HistoryItem> createItemTree(Frame* targetFrame, bool clipAtTarget); - - void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType); - bool currentFramesMatchItem(HistoryItem*) const; - void updateBackForwardListClippedAtTarget(bool doClip); - - Frame* m_frame; - - RefPtr<HistoryItem> m_currentItem; - RefPtr<HistoryItem> m_previousItem; - RefPtr<HistoryItem> m_provisionalItem; - - bool m_frameLoadComplete; -}; - -} // namespace WebCore - -#endif // HistoryController_h diff --git a/WebCore/loader/ImageLoader.cpp b/WebCore/loader/ImageLoader.cpp deleted file mode 100644 index 94a21a4..0000000 --- a/WebCore/loader/ImageLoader.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 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 "CachedImage.h" -#include "CachedResourceLoader.h" -#include "Document.h" -#include "Element.h" -#include "HTMLNames.h" -#include "HTMLObjectElement.h" -#include "RenderImage.h" - -#if ENABLE(SVG) -#include "RenderSVGImage.h" -#endif -#if ENABLE(VIDEO) -#include "RenderVideo.h" -#endif - -#if !ASSERT_DISABLED -// ImageLoader objects are allocated as members of other objects, so generic pointer check would always fail. -namespace WTF { - -template<> struct ValueCheck<WebCore::ImageLoader*> { - typedef WebCore::ImageLoader* TraitType; - static void checkConsistency(const WebCore::ImageLoader* p) - { - if (!p) - return; - ASSERT(p->element()); - ValueCheck<WebCore::Element*>::checkConsistency(p->element()); - } -}; - -} -#endif - -namespace WebCore { - -class ImageEventSender : public Noncopyable { -public: - ImageEventSender(const AtomicString& eventType); - - void dispatchEventSoon(ImageLoader*); - void cancelEvent(ImageLoader*); - - void dispatchPendingEvents(); - -#if !ASSERT_DISABLED - bool hasPendingEvents(ImageLoader* loader) { return m_dispatchSoonList.find(loader) != notFound; } -#endif - -private: - void timerFired(Timer<ImageEventSender>*); - - AtomicString m_eventType; - Timer<ImageEventSender> m_timer; - Vector<ImageLoader*> m_dispatchSoonList; - Vector<ImageLoader*> m_dispatchingList; -}; - -static ImageEventSender& beforeLoadEventSender() -{ - DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().beforeloadEvent)); - return sender; -} - -static ImageEventSender& loadEventSender() -{ - DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().loadEvent)); - return sender; -} - -ImageLoader::ImageLoader(Element* element) - : m_element(element) - , m_image(0) - , m_firedBeforeLoad(true) - , m_firedLoad(true) - , m_imageComplete(true) - , m_loadManually(false) -{ -} - -ImageLoader::~ImageLoader() -{ - if (m_image) - m_image->removeClient(this); - - ASSERT(!m_firedBeforeLoad || !beforeLoadEventSender().hasPendingEvents(this)); - if (!m_firedBeforeLoad) - beforeLoadEventSender().cancelEvent(this); - - ASSERT(!m_firedLoad || !loadEventSender().hasPendingEvents(this)); - if (!m_firedLoad) - loadEventSender().cancelEvent(this); -} - -void ImageLoader::setImage(CachedImage* newImage) -{ - ASSERT(m_failedLoadURL.isEmpty()); - CachedImage* oldImage = m_image.get(); - if (newImage != oldImage) { - m_image = newImage; - if (!m_firedBeforeLoad) { - beforeLoadEventSender().cancelEvent(this); - m_firedBeforeLoad = true; - } - if (!m_firedLoad) { - loadEventSender().cancelEvent(this); - m_firedLoad = true; - } - m_imageComplete = true; - if (newImage) - newImage->addClient(this); - if (oldImage) - oldImage->removeClient(this); - } - - if (RenderImageResource* imageResource = renderImageResource()) - imageResource->resetAnimation(); -} - -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. - Document* document = m_element->document(); - if (!document->renderer()) - return; - - AtomicString attr = m_element->getAttribute(m_element->imageSourceAttributeName()); - - if (attr == m_failedLoadURL) - return; - - // 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() && document->baseURI().isLocalFile()))) { - if (m_loadManually) { - bool autoLoadOtherImages = document->cachedResourceLoader()->autoLoadImages(); - document->cachedResourceLoader()->setAutoLoadImages(false); - newImage = new CachedImage(sourceURI(attr)); - newImage->setLoading(true); - newImage->setCachedResourceLoader(document->cachedResourceLoader()); - document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage); - document->cachedResourceLoader()->setAutoLoadImages(autoLoadOtherImages); - } else - newImage = document->cachedResourceLoader()->requestImage(sourceURI(attr)); - - // If we do not have an image here, it means that a cross-site - // violation occurred. - m_failedLoadURL = !newImage ? attr : AtomicString(); - } - - CachedImage* oldImage = m_image.get(); - if (newImage != oldImage) { - if (!m_firedBeforeLoad) - beforeLoadEventSender().cancelEvent(this); - if (!m_firedLoad) - loadEventSender().cancelEvent(this); - - m_image = newImage; - m_firedBeforeLoad = !newImage; - m_firedLoad = !newImage; - m_imageComplete = !newImage; - - if (newImage) { - newImage->addClient(this); - if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) - dispatchPendingBeforeLoadEvent(); - else - beforeLoadEventSender().dispatchEventSoon(this); - } - if (oldImage) - oldImage->removeClient(this); - } - - if (RenderImageResource* imageResource = renderImageResource()) - imageResource->resetAnimation(); -} - -void ImageLoader::updateFromElementIgnoringPreviousError() -{ - // Clear previous error. - m_failedLoadURL = AtomicString(); - updateFromElement(); -} - -void ImageLoader::notifyFinished(CachedResource*) -{ - ASSERT(m_failedLoadURL.isEmpty()); - - m_imageComplete = true; - if (haveFiredBeforeLoadEvent()) - updateRenderer(); - - if (m_firedLoad) - return; - - loadEventSender().dispatchEventSoon(this); -} - -RenderImageResource* ImageLoader::renderImageResource() -{ - RenderObject* renderer = m_element->renderer(); - - if (!renderer) - return 0; - - if (renderer->isImage()) - return toRenderImage(renderer)->imageResource(); - -#if ENABLE(SVG) - if (renderer->isSVGImage()) - return toRenderSVGImage(renderer)->imageResource(); -#endif - -#if ENABLE(VIDEO) - if (renderer->isVideo()) - return toRenderVideo(renderer)->imageResource(); -#endif - - return 0; -} - -void ImageLoader::updateRenderer() -{ - RenderImageResource* imageResource = renderImageResource(); - - if (!imageResource) - return; - - // Only update the renderer if it doesn't have an image or if what we have - // is a complete image. This prevents flickering in the case where a dynamic - // change is happening between two images. - CachedImage* cachedImage = imageResource->cachedImage(); - if (m_image != cachedImage && (m_imageComplete || !cachedImage)) - imageResource->setCachedImage(m_image.get()); -} - -void ImageLoader::dispatchPendingBeforeLoadEvent() -{ - if (m_firedBeforeLoad) - return; - if (!m_image) - return; - if (!m_element->document()->attached()) - return; - m_firedBeforeLoad = true; - if (m_element->dispatchBeforeLoadEvent(m_image->url())) { - updateRenderer(); - return; - } - if (m_image) { - m_image->removeClient(this); - m_image = 0; - } - loadEventSender().cancelEvent(this); - - if (m_element->hasTagName(HTMLNames::objectTag)) - static_cast<HTMLObjectElement*>(m_element)->renderFallbackContent(); -} - -void ImageLoader::dispatchPendingLoadEvent() -{ - if (m_firedLoad) - return; - if (!m_image) - return; - if (!m_element->document()->attached()) - return; - m_firedLoad = true; - dispatchLoadEvent(); -} - -void ImageLoader::dispatchPendingBeforeLoadEvents() -{ - beforeLoadEventSender().dispatchPendingEvents(); -} - -void ImageLoader::dispatchPendingLoadEvents() -{ - loadEventSender().dispatchPendingEvents(); -} - -void ImageLoader::elementWillMoveToNewOwnerDocument() -{ - setImage(0); -} - -ImageEventSender::ImageEventSender(const AtomicString& eventType) - : m_eventType(eventType) - , m_timer(this, &ImageEventSender::timerFired) -{ -} - -void ImageEventSender::dispatchEventSoon(ImageLoader* loader) -{ - m_dispatchSoonList.append(loader); - if (!m_timer.isActive()) - m_timer.startOneShot(0); -} - -void ImageEventSender::cancelEvent(ImageLoader* loader) -{ - // Remove instances of this loader from both lists. - // Use loops because we allow multiple instances to get into the lists. - size_t size = m_dispatchSoonList.size(); - for (size_t i = 0; i < size; ++i) { - if (m_dispatchSoonList[i] == loader) - m_dispatchSoonList[i] = 0; - } - size = m_dispatchingList.size(); - for (size_t i = 0; i < size; ++i) { - if (m_dispatchingList[i] == loader) - m_dispatchingList[i] = 0; - } - if (m_dispatchSoonList.isEmpty()) - m_timer.stop(); -} - -void ImageEventSender::dispatchPendingEvents() -{ - // Need to avoid re-entering this function; if new dispatches are - // scheduled before the parent finishes processing the list, they - // will set a timer and eventually be processed. - if (!m_dispatchingList.isEmpty()) - return; - - m_timer.stop(); - - m_dispatchSoonList.checkConsistency(); - - m_dispatchingList.swap(m_dispatchSoonList); - size_t size = m_dispatchingList.size(); - for (size_t i = 0; i < size; ++i) { - if (ImageLoader* loader = m_dispatchingList[i]) { - if (m_eventType == eventNames().beforeloadEvent) - loader->dispatchPendingBeforeLoadEvent(); - else - loader->dispatchPendingLoadEvent(); - } - } - m_dispatchingList.clear(); -} - -void ImageEventSender::timerFired(Timer<ImageEventSender>*) -{ - dispatchPendingEvents(); -} - -} diff --git a/WebCore/loader/ImageLoader.h b/WebCore/loader/ImageLoader.h deleted file mode 100644 index 9bf7624..0000000 --- a/WebCore/loader/ImageLoader.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2009 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 ImageLoader_h -#define ImageLoader_h - -#include "CachedResourceClient.h" -#include "CachedResourceHandle.h" -#include <wtf/text/AtomicString.h> - -namespace WebCore { - -class Element; -class ImageLoadEventSender; -class RenderImageResource; - -class ImageLoader : public CachedResourceClient { -public: - ImageLoader(Element*); - virtual ~ImageLoader(); - - // This function should be called when the element is attached to a document; starts - // loading if a load hasn't already been started. - void updateFromElement(); - - // This function should be called whenever the 'src' attribute is set, even if its value - // doesn't change; starts new load unconditionally (matches Firefox and Opera behavior). - void updateFromElementIgnoringPreviousError(); - - void elementWillMoveToNewOwnerDocument(); - - Element* element() const { return m_element; } - bool imageComplete() const { return m_imageComplete; } - - CachedImage* image() const { return m_image.get(); } - void setImage(CachedImage*); // Cancels pending beforeload and load events, and doesn't dispatch new ones. - - void setLoadManually(bool loadManually) { m_loadManually = loadManually; } - - bool haveFiredBeforeLoadEvent() const { return m_firedBeforeLoad; } - bool haveFiredLoadEvent() const { return m_firedLoad; } - - static void dispatchPendingBeforeLoadEvents(); - static void dispatchPendingLoadEvents(); - -protected: - virtual void notifyFinished(CachedResource*); - -private: - virtual void dispatchLoadEvent() = 0; - virtual String sourceURI(const AtomicString&) const = 0; - - friend class ImageEventSender; - void dispatchPendingBeforeLoadEvent(); - void dispatchPendingLoadEvent(); - - RenderImageResource* renderImageResource(); - void updateRenderer(); - - Element* m_element; - CachedResourceHandle<CachedImage> m_image; - AtomicString m_failedLoadURL; - bool m_firedBeforeLoad : 1; - 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 85ceb19..0000000 --- a/WebCore/loader/MainResourceLoader.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "MainResourceLoader.h" - -#include "ApplicationCacheHost.h" -#include "DocumentLoadTiming.h" -#include "DocumentLoader.h" -#include "FormState.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLFormElement.h" -#include "Page.h" -#if PLATFORM(QT) -#include "PluginDatabase.h" -#endif -#include "ResourceError.h" -#include "ResourceHandle.h" -#include "ResourceLoadScheduler.h" -#include "SchemeRegistry.h" -#include "Settings.h" -#include <wtf/CurrentTime.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()->notifier()->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()->policyChecker()->cancelCheck(); - 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(); - else if (m_substituteData.isValid()) { - // A redirect resulted in loading substitute data. - ASSERT(documentLoader()->timing()->redirectCount); - handle()->cancel(); - handleDataLoadSoon(request); - } - - 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); - documentLoader()->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); - - ASSERT(documentLoader()->timing()->fetchStart); - if (!redirectResponse.isNull()) { - DocumentLoadTiming* documentLoadTiming = documentLoader()->timing(); - documentLoadTiming->redirectCount++; - if (!documentLoadTiming->redirectStart) - documentLoadTiming->redirectStart = documentLoadTiming->fetchStart; - documentLoadTiming->redirectEnd = currentTime(); - documentLoadTiming->fetchStart = documentLoadTiming->redirectEnd; - } - - // 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.setFirstPartyForCookies(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); - - Frame* top = m_frame->tree()->top(); - if (top != m_frame) - frameLoader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url()); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (!redirectResponse.isNull()) { - // We checked application cache for initial URL, now we need to check it for redirected one. - ASSERT(!m_substituteData.isValid()); - documentLoader()->applicationCacheHost()->maybeLoadMainResourceForRedirect(newRequest, m_substituteData); - } -#endif - - // 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. - if (!redirectResponse.isNull()) { - ref(); // balanced by deref in continueAfterNavigationPolicy - frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this); - } -} - -static bool shouldLoadAsEmptyDocument(const KURL& url) -{ -#if PLATFORM(TORCHMOBILE) - return url.isEmpty() || (url.protocolIs("about") && equalIgnoringRef(url, blankURL())); -#else - return url.isEmpty() || SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(url.protocol()); -#endif -} - -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()->policyChecker()->cannotShowMIMEType(r); - // Check reachedTerminalState since the load may have already been cancelled inside of _handleUnimplementablePolicyWithErrorCode::. - if (!reachedTerminalState()) - stopLoadingForPolicyChange(); - return; - } - break; - } - - case PolicyDownload: - // m_handle can be null, e.g. when loading a substitute resource from application cache. - if (!m_handle) { - receivedError(cannotShowURLError()); - return; - } - frameLoader()->client()->download(m_handle.get(), request(), m_handle.get()->firstRequest(), 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(0); - } else if (shouldLoadAsEmptyDocument(url) || frameLoader()->representationExistsForURLScheme(url.protocol())) - didFinishLoading(0); - } -} - -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 -} - -#if PLATFORM(QT) -void MainResourceLoader::substituteMIMETypeFromPluginDatabase(const ResourceResponse& r) -{ - if (!m_frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin)) - return; - - String filename = r.url().lastPathComponent(); - if (filename.endsWith("/")) - return; - - size_t extensionPos = filename.reverseFind('.'); - if (extensionPos == notFound) - return; - - String extension = filename.substring(extensionPos + 1); - String mimeType = PluginDatabase::installedPlugins()->MIMETypeForExtension(extension); - if (!mimeType.isEmpty()) { - ResourceResponse* response = const_cast<ResourceResponse*>(&r); - response->setMimeType(mimeType); - } -} -#endif - -void MainResourceLoader::didReceiveResponse(const ResourceResponse& r) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainResponse(request(), r)) - return; -#endif - - HTTPHeaderMap::const_iterator it = r.httpHeaderFields().find(AtomicString("x-frame-options")); - if (it != r.httpHeaderFields().end()) { - String content = it->second; - if (m_frame->loader()->shouldInterruptLoadForXFrameOptions(content, r.url())) { - cancel(); - return; - } - } - - // 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 PLATFORM(QT) - if (r.mimeType() == "application/octet-stream") - substituteMIMETypeFromPluginDatabase(r); -#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 - - ASSERT(frameLoader()->activeDocumentLoader()); - - // Always show content with valid substitute data. - if (frameLoader()->activeDocumentLoader()->substituteData().isValid()) { - callContinueAfterContentPolicy(this, 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() && m_response.mimeType() == "application/x-ftp-directory") { - callContinueAfterContentPolicy(this, PolicyUse); - return; - } -#endif - - frameLoader()->policyChecker()->checkContentPolicy(m_response.mimeType(), callContinueAfterContentPolicy, this); -} - -void MainResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) -{ - ASSERT(data); - ASSERT(length != 0); - - ASSERT(!m_response.isNull()); - -#if USE(CFNETWORK) || (PLATFORM(MAC) && !defined(BUILDING_ON_TIGER)) - // Workaround for <rdar://problem/6060782> - if (m_response.isNull()) { - m_response = ResourceResponse(KURL(), "text/html", 0, String(), String()); - if (DocumentLoader* documentLoader = frameLoader()->activeDocumentLoader()) - documentLoader->setResponse(m_response); - } -#endif - - // 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 - - #if ENABLE(OFFLINE_WEB_APPLICATIONS) - documentLoader()->applicationCacheHost()->mainResourceDataReceived(data, length, lengthReceived, allAtOnce); -#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); - - m_timeOfLastDataReceived = currentTime(); - - ResourceLoader::didReceiveData(data, length, lengthReceived, allAtOnce); -} - -void MainResourceLoader::didFinishLoading(double finishTime) -{ - // 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 - - ASSERT(!documentLoader()->timing()->responseEnd); - documentLoader()->timing()->responseEnd = finishTime ? finishTime : m_timeOfLastDataReceived; - frameLoader()->finishedLoading(); - ResourceLoader::didFinishLoading(finishTime); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - dl->applicationCacheHost()->finishedLoadingMainResource(); -#endif -} - -void MainResourceLoader::didFail(const ResourceError& error) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainError(request(), error)) - return; -#endif - - // 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(MainResourceLoaderTimer*) -{ - RefPtr<MainResourceLoader> protect(this); - - KURL url = m_substituteData.responseURL(); - if (url.isEmpty()) - url = m_initialRequest.url(); - - // Clear the initial request here so that subsequent entries into the - // loader will not think there's still a deferred load left to do. - m_initialRequest = ResourceRequest(); - - ResourceResponse response(url, m_substituteData.mimeType(), m_substituteData.content()->size(), m_substituteData.textEncoding(), ""); - didReceiveResponse(response); -} - -void MainResourceLoader::startDataLoadTimer() -{ - m_dataLoadTimer.startOneShot(0); - -#if HAVE(RUNLOOP_TIMER) - if (SchedulePairHashSet* scheduledPairs = m_frame->page()->scheduledRunLoopPairs()) - m_dataLoadTimer.schedule(*scheduledPairs); -#endif -} - -void MainResourceLoader::handleDataLoadSoon(const ResourceRequest& r) -{ - m_initialRequest = r; - - if (m_documentLoader->deferMainResourceDataLoad()) - startDataLoadTimer(); - 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; - - resourceLoadScheduler()->addMainResourceLoad(this); - if (m_substituteData.isValid()) - handleDataLoadSoon(r); - else if (shouldLoadEmpty || frameLoader()->representationExistsForURLScheme(url.protocol())) - handleEmptyLoad(url, !shouldLoadEmpty); - else - m_handle = ResourceHandle::create(m_frame->loader()->networkingContext(), r, this, false, true); - - return false; -} - -bool MainResourceLoader::load(const ResourceRequest& r, const SubstituteData& substituteData) -{ - ASSERT(!m_handle); - - m_substituteData = substituteData; - - ASSERT(documentLoader()->timing()->navigationStart); - ASSERT(!documentLoader()->timing()->fetchStart); - documentLoader()->timing()->fetchStart = currentTime(); - ResourceRequest request(r); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - documentLoader()->applicationCacheHost()->maybeLoadMainResource(request, m_substituteData); -#endif - - bool defer = defersLoading(); - if (defer) { - bool shouldLoadEmpty = shouldLoadAsEmptyDocument(request.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()) - startDataLoadTimer(); - 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 1620f7a..0000000 --- a/WebCore/loader/MainResourceLoader.h +++ /dev/null @@ -1,115 +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. - */ - -#ifndef MainResourceLoader_h -#define MainResourceLoader_h - -#include "FrameLoaderTypes.h" -#include "ResourceLoader.h" -#include "SubstituteData.h" -#include <wtf/Forward.h> - -#if HAVE(RUNLOOP_TIMER) -#include "RunLoopTimer.h" -#else -#include "Timer.h" -#endif - -namespace WebCore { - - 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(double finishTime); - virtual void didFail(const ResourceError&); - -#if HAVE(RUNLOOP_TIMER) - typedef RunLoopTimer<MainResourceLoader> MainResourceLoaderTimer; -#else - typedef Timer<MainResourceLoader> MainResourceLoaderTimer; -#endif - - void handleDataLoadNow(MainResourceLoaderTimer*); - - bool isLoadingMultipartContent() const { return m_loadingMultipartContent; } - - private: - MainResourceLoader(Frame*); - - virtual void didCancel(const ResourceError&); - - bool loadNow(ResourceRequest&); - - void handleEmptyLoad(const KURL&, bool forURLScheme); - void handleDataLoadSoon(const ResourceRequest& r); - - void startDataLoadTimer(); - 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&); - -#if PLATFORM(QT) - void substituteMIMETypeFromPluginDatabase(const ResourceResponse&); -#endif - - ResourceRequest m_initialRequest; - SubstituteData m_substituteData; - - MainResourceLoaderTimer m_dataLoadTimer; - - bool m_loadingMultipartContent; - bool m_waitingForContentPolicy; - double m_timeOfLastDataReceived; - }; - -} - -#endif diff --git a/WebCore/loader/NavigationAction.cpp b/WebCore/loader/NavigationAction.cpp deleted file mode 100644 index ed68e43..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 || frameLoadType == FrameLoadTypeReloadFromOrigin) - 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/NavigationScheduler.cpp b/WebCore/loader/NavigationScheduler.cpp deleted file mode 100644 index d2d0f7f..0000000 --- a/WebCore/loader/NavigationScheduler.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) 2009 Adam Barth. 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 "NavigationScheduler.h" - -#include "BackForwardController.h" -#include "DOMWindow.h" -#include "DocumentLoader.h" -#include "Event.h" -#include "FormState.h" -#include "FormSubmission.h" -#include "Frame.h" -#include "FrameLoadRequest.h" -#include "FrameLoader.h" -#include "FrameLoaderStateMachine.h" -#include "HTMLFormElement.h" -#include "HTMLFrameOwnerElement.h" -#include "HistoryItem.h" -#include "Page.h" -#include "UserGestureIndicator.h" -#include <wtf/CurrentTime.h> - -namespace WebCore { - -class ScheduledNavigation : public Noncopyable { -public: - ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList, bool wasDuringLoad, bool isLocationChange) - : m_delay(delay) - , m_lockHistory(lockHistory) - , m_lockBackForwardList(lockBackForwardList) - , m_wasDuringLoad(wasDuringLoad) - , m_isLocationChange(isLocationChange) - , m_wasUserGesture(ScriptController::processingUserGesture()) - { - } - virtual ~ScheduledNavigation() { } - - virtual void fire(Frame*) = 0; - - virtual bool shouldStartTimer(Frame*) { return true; } - virtual void didStartTimer(Frame*, Timer<NavigationScheduler>*) { } - virtual void didStopTimer(Frame*, bool /* newLoadInProgress */) { } - - double delay() const { return m_delay; } - bool lockHistory() const { return m_lockHistory; } - bool lockBackForwardList() const { return m_lockBackForwardList; } - bool wasDuringLoad() const { return m_wasDuringLoad; } - bool isLocationChange() const { return m_isLocationChange; } - bool wasUserGesture() const { return m_wasUserGesture; } - -protected: - void clearUserGesture() { m_wasUserGesture = false; } - -private: - double m_delay; - bool m_lockHistory; - bool m_lockBackForwardList; - bool m_wasDuringLoad; - bool m_isLocationChange; - bool m_wasUserGesture; -}; - -class ScheduledURLNavigation : public ScheduledNavigation { -protected: - ScheduledURLNavigation(double delay, PassRefPtr<SecurityOrigin> securityOrigin, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool duringLoad, bool isLocationChange) - : ScheduledNavigation(delay, lockHistory, lockBackForwardList, duringLoad, isLocationChange) - , m_securityOrigin(securityOrigin) - , m_url(url) - , m_referrer(referrer) - , m_haveToldClient(false) - { - } - - virtual void fire(Frame* frame) - { - UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); - frame->loader()->changeLocation(m_securityOrigin, KURL(ParsedURLString, m_url), m_referrer, lockHistory(), lockBackForwardList(), false); - } - - virtual void didStartTimer(Frame* frame, Timer<NavigationScheduler>* timer) - { - if (m_haveToldClient) - return; - m_haveToldClient = true; - frame->loader()->clientRedirected(KURL(ParsedURLString, m_url), delay(), currentTime() + timer->nextFireInterval(), lockBackForwardList()); - } - - virtual void didStopTimer(Frame* frame, bool newLoadInProgress) - { - if (!m_haveToldClient) - return; - frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); - } - - SecurityOrigin* securityOrigin() const { return m_securityOrigin.get(); } - String url() const { return m_url; } - String referrer() const { return m_referrer; } - -private: - RefPtr<SecurityOrigin> m_securityOrigin; - String m_url; - String m_referrer; - bool m_haveToldClient; -}; - -class ScheduledRedirect : public ScheduledURLNavigation { -public: - ScheduledRedirect(double delay, PassRefPtr<SecurityOrigin> securityOrigin, const String& url, bool lockHistory, bool lockBackForwardList) - : ScheduledURLNavigation(delay, securityOrigin, url, String(), lockHistory, lockBackForwardList, false, false) - { - clearUserGesture(); - } - - virtual bool shouldStartTimer(Frame* frame) { return frame->loader()->allAncestorsAreComplete(); } -}; - -class ScheduledLocationChange : public ScheduledURLNavigation { -public: - ScheduledLocationChange(PassRefPtr<SecurityOrigin> securityOrigin, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool duringLoad) - : ScheduledURLNavigation(0.0, securityOrigin, url, referrer, lockHistory, lockBackForwardList, duringLoad, true) { } -}; - -class ScheduledRefresh : public ScheduledURLNavigation { -public: - ScheduledRefresh(PassRefPtr<SecurityOrigin> securityOrigin, const String& url, const String& referrer) - : ScheduledURLNavigation(0.0, securityOrigin, url, referrer, true, true, false, true) - { - } - - virtual void fire(Frame* frame) - { - UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); - frame->loader()->changeLocation(securityOrigin(), KURL(ParsedURLString, url()), referrer(), lockHistory(), lockBackForwardList(), true); - } -}; - -class ScheduledHistoryNavigation : public ScheduledNavigation { -public: - explicit ScheduledHistoryNavigation(int historySteps) - : ScheduledNavigation(0, false, false, false, true) - , m_historySteps(historySteps) - { - } - - virtual void fire(Frame* frame) - { - UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); - - FrameLoader* loader = frame->loader(); - if (!m_historySteps) { - // Special case for go(0) from a frame -> reload only the frame - // To follow Firefox and IE's behavior, history reload can only navigate the self frame. - loader->urlSelected(loader->url(), "_self", 0, lockHistory(), lockBackForwardList(), SendReferrer); - 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. - frame->page()->backForward()->goBackOrForward(m_historySteps); - } - -private: - int m_historySteps; -}; - -class ScheduledFormSubmission : public ScheduledNavigation { -public: - ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBackForwardList, bool duringLoad) - : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList, duringLoad, true) - , m_submission(submission) - , m_haveToldClient(false) - { - ASSERT(m_submission->state()); - } - - virtual void fire(Frame* frame) - { - UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); - - // The submitForm function will find a target frame before using the redirection timer. - // Now that the timer has fired, we need to repeat the security check which normally is done when - // selecting a target, in case conditions have changed. Other code paths avoid this by targeting - // without leaving a time window. If we fail the check just silently drop the form submission. - Frame* requestingFrame = m_submission->state()->sourceFrame(); - if (!requestingFrame->loader()->shouldAllowNavigation(frame)) - return; - FrameLoadRequest frameRequest(requestingFrame->document()->securityOrigin()); - m_submission->populateFrameLoadRequest(frameRequest); - frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackForwardList(), m_submission->event(), m_submission->state(), SendReferrer); - } - - virtual void didStartTimer(Frame* frame, Timer<NavigationScheduler>* timer) - { - if (m_haveToldClient) - return; - m_haveToldClient = true; - frame->loader()->clientRedirected(m_submission->requestURL(), delay(), currentTime() + timer->nextFireInterval(), lockBackForwardList()); - } - - virtual void didStopTimer(Frame* frame, bool newLoadInProgress) - { - if (!m_haveToldClient) - return; - frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); - } - -private: - RefPtr<FormSubmission> m_submission; - bool m_haveToldClient; -}; - -NavigationScheduler::NavigationScheduler(Frame* frame) - : m_frame(frame) - , m_timer(this, &NavigationScheduler::timerFired) -{ -} - -NavigationScheduler::~NavigationScheduler() -{ -} - -bool NavigationScheduler::redirectScheduledDuringLoad() -{ - return m_redirect && m_redirect->wasDuringLoad(); -} - -bool NavigationScheduler::locationChangePending() -{ - return m_redirect && m_redirect->isLocationChange(); -} - -void NavigationScheduler::clear() -{ - m_timer.stop(); - m_redirect.clear(); -} - -void NavigationScheduler::scheduleRedirect(double delay, const String& url) -{ - if (!m_frame->page()) - return; - if (delay < 0 || delay > INT_MAX / 1000) - return; - if (url.isEmpty()) - return; - - // We want a new back/forward list item if the refresh timeout is > 1 second. - if (!m_redirect || delay <= m_redirect->delay()) - schedule(adoptPtr(new ScheduledRedirect(delay, m_frame->document()->securityOrigin(), url, true, delay <= 1))); -} - -bool NavigationScheduler::mustLockBackForwardList(Frame* targetFrame) -{ - // Non-user navigation before the page has finished firing onload should not create a new back/forward item. - // See https://webkit.org/b/42861 for the original motivation for this. - if (!ScriptController::processingUserGesture() && targetFrame->loader()->documentLoader() && !targetFrame->loader()->documentLoader()->wasOnloadHandled()) - return true; - - // Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item. - // The definition of "during load" is any time before all handlers for the load event have been run. - // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this. - for (Frame* ancestor = targetFrame->tree()->parent(); ancestor; ancestor = ancestor->tree()->parent()) { - Document* document = ancestor->document(); - if (!ancestor->loader()->isComplete() || (document && document->processingLoadEvent())) - return true; - } - return false; -} - -void NavigationScheduler::scheduleLocationChange(PassRefPtr<SecurityOrigin> securityOrigin, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList) -{ - if (!m_frame->page()) - return; - if (url.isEmpty()) - return; - - lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame); - - FrameLoader* loader = m_frame->loader(); - - // 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(ParsedURLString, url); - if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(loader->url(), parsedURL)) { - loader->changeLocation(securityOrigin, loader->completeURL(url), referrer, lockHistory, lockBackForwardList); - 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 = !loader->stateMachine()->committedFirstRealDocumentLoad(); - - schedule(adoptPtr(new ScheduledLocationChange(securityOrigin, url, referrer, lockHistory, lockBackForwardList, duringLoad))); -} - -void NavigationScheduler::scheduleFormSubmission(PassRefPtr<FormSubmission> submission) -{ - ASSERT(m_frame->page()); - - // FIXME: Do we need special handling for form submissions where the URL is the same - // as the current one except for the fragment part? See scheduleLocationChange above. - - // 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_frame->loader()->stateMachine()->committedFirstRealDocumentLoad(); - - // If this is a child frame and the form submission was triggered by a script, lock the back/forward list - // to match IE and Opera. - // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this. - bool lockBackForwardList = mustLockBackForwardList(m_frame) - || (submission->state()->formSubmissionTrigger() == SubmittedByJavaScript - && m_frame->tree()->parent() && !ScriptController::processingUserGesture()); - - schedule(adoptPtr(new ScheduledFormSubmission(submission, lockBackForwardList, duringLoad))); -} - -void NavigationScheduler::scheduleRefresh() -{ - if (!m_frame->page()) - return; - const KURL& url = m_frame->loader()->url(); - if (url.isEmpty()) - return; - - schedule(adoptPtr(new ScheduledRefresh(m_frame->document()->securityOrigin(), url.string(), m_frame->loader()->outgoingReferrer()))); -} - -void NavigationScheduler::scheduleHistoryNavigation(int steps) -{ - if (!m_frame->page()) - return; - - // Invalid history navigations (such as history.forward() during a new load) have the side effect of cancelling any scheduled - // redirects. We also avoid the possibility of cancelling the current load by avoiding the scheduled redirection altogether. - BackForwardController* backForward = m_frame->page()->backForward(); - if (steps > backForward->forwardCount() || -steps > backForward->backCount()) { - cancel(); - return; - } - - // In all other cases, schedule the history traversal to occur asynchronously. - schedule(adoptPtr(new ScheduledHistoryNavigation(steps))); -} - -void NavigationScheduler::timerFired(Timer<NavigationScheduler>*) -{ - if (!m_frame->page()) - return; - if (m_frame->page()->defersLoading()) - return; - - OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); - redirect->fire(m_frame); -} - -void NavigationScheduler::schedule(PassOwnPtr<ScheduledNavigation> redirect) -{ - ASSERT(m_frame->page()); - - // 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 (redirect->wasDuringLoad()) { - if (DocumentLoader* provisionalDocumentLoader = m_frame->loader()->provisionalDocumentLoader()) - provisionalDocumentLoader->stopLoading(); - m_frame->loader()->stopLoading(UnloadEventPolicyUnloadAndPageHide); - } - - cancel(); - m_redirect = redirect; - - if (!m_frame->loader()->isComplete() && m_redirect->isLocationChange()) - m_frame->loader()->completed(); - - startTimer(); -} - -void NavigationScheduler::startTimer() -{ - if (!m_redirect) - return; - - ASSERT(m_frame->page()); - if (m_timer.isActive()) - return; - if (!m_redirect->shouldStartTimer(m_frame)) - return; - - m_timer.startOneShot(m_redirect->delay()); - m_redirect->didStartTimer(m_frame, &m_timer); -} - -void NavigationScheduler::cancel(bool newLoadInProgress) -{ - m_timer.stop(); - - OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); - if (redirect) - redirect->didStopTimer(m_frame, newLoadInProgress); -} - -} // namespace WebCore diff --git a/WebCore/loader/NavigationScheduler.h b/WebCore/loader/NavigationScheduler.h deleted file mode 100644 index 4f3bebc..0000000 --- a/WebCore/loader/NavigationScheduler.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) 2009 Adam Barth. 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 NavigationScheduler_h -#define NavigationScheduler_h - -#include "Event.h" -#include "Timer.h" -#include <wtf/Forward.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -class FormState; -class FormSubmission; -class Frame; -class ScheduledNavigation; -class SecurityOrigin; - -struct FrameLoadRequest; - -class NavigationScheduler : public Noncopyable { -public: - NavigationScheduler(Frame*); - ~NavigationScheduler(); - - bool redirectScheduledDuringLoad(); - bool locationChangePending(); - - void scheduleRedirect(double delay, const String& url); - void scheduleLocationChange(PassRefPtr<SecurityOrigin>, const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true); - void scheduleFormSubmission(PassRefPtr<FormSubmission>); - void scheduleRefresh(); - void scheduleHistoryNavigation(int steps); - - void startTimer(); - - void cancel(bool newLoadInProgress = false); - void clear(); - -private: - void timerFired(Timer<NavigationScheduler>*); - void schedule(PassOwnPtr<ScheduledNavigation>); - - static bool mustLockBackForwardList(Frame* targetFrame); - - Frame* m_frame; - Timer<NavigationScheduler> m_timer; - OwnPtr<ScheduledNavigation> m_redirect; -}; - -} // namespace WebCore - -#endif // NavigationScheduler_h diff --git a/WebCore/loader/NetscapePlugInStreamLoader.cpp b/WebCore/loader/NetscapePlugInStreamLoader.cpp deleted file mode 100644 index 75a2fe9..0000000 --- a/WebCore/loader/NetscapePlugInStreamLoader.cpp +++ /dev/null @@ -1,141 +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, const ResourceRequest& request) -{ - RefPtr<NetscapePlugInStreamLoader> loader(adoptRef(new NetscapePlugInStreamLoader(frame, client))); - loader->setShouldBufferData(false); - loader->documentLoader()->addPlugInStreamLoader(loader.get()); - if (!loader->init(request)) - return 0; - - return loader.release(); -} - -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(double finishTime) -{ - RefPtr<NetscapePlugInStreamLoader> protect(this); - - m_documentLoader->removePlugInStreamLoader(this); - m_client->didFinishLoading(this); - ResourceLoader::didFinishLoading(finishTime); -} - -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); - - // If calling didFail spins the run loop the stream loader can reach the terminal state. - // If that's the case we just return early. - if (reachedTerminalState()) - return; - - // 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 4d7d03b..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*, const ResourceRequest&); - 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(double finishTime); - 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/PingLoader.cpp b/WebCore/loader/PingLoader.cpp deleted file mode 100644 index d687b42..0000000 --- a/WebCore/loader/PingLoader.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "PingLoader.h" - -#include "FormData.h" -#include "Frame.h" -#include "ResourceHandle.h" -#include "SecurityOrigin.h" -#include <wtf/OwnPtr.h> -#include <wtf/UnusedParam.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -void PingLoader::loadImage(Frame* frame, const KURL& url) -{ - if (!frame->document()->securityOrigin()->canDisplay(url)) { - FrameLoader::reportLocalLoadFailed(frame, url); - return; - } - - ResourceRequest request(url); - request.setTargetType(ResourceRequest::TargetIsImage); - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - if (!SecurityOrigin::shouldHideReferrer(request.url(), frame->loader()->outgoingReferrer())) - request.setHTTPReferrer(frame->loader()->outgoingReferrer()); - frame->loader()->addExtraFieldsToSubresourceRequest(request); - OwnPtr<PingLoader> pingLoader = adoptPtr(new PingLoader(frame, request)); - - // Leak the ping loader, since it will kill itself as soon as it receives a response. - PingLoader* leakedPingLoader = pingLoader.leakPtr(); - UNUSED_PARAM(leakedPingLoader); -} - -// http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing -void PingLoader::sendPing(Frame* frame, const KURL& pingURL, const KURL& destinationURL) -{ - ResourceRequest request(pingURL); - request.setTargetType(ResourceRequest::TargetIsSubresource); - request.setHTTPMethod("POST"); - request.setHTTPContentType("text/ping"); - request.setHTTPBody(FormData::create("PING")); - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - frame->loader()->addExtraFieldsToSubresourceRequest(request); - - SecurityOrigin* sourceOrigin = frame->document()->securityOrigin(); - RefPtr<SecurityOrigin> pingOrigin = SecurityOrigin::create(pingURL); - FrameLoader::addHTTPOriginIfNeeded(request, sourceOrigin->toString()); - request.setHTTPHeaderField("Ping-To", destinationURL); - if (sourceOrigin->isSameSchemeHostPort(pingOrigin.get())) - request.setHTTPHeaderField("Ping-From", frame->document()->url()); - else if (!SecurityOrigin::shouldHideReferrer(pingURL, frame->loader()->outgoingReferrer())) - request.setHTTPReferrer(frame->loader()->outgoingReferrer()); - OwnPtr<PingLoader> pingLoader = adoptPtr(new PingLoader(frame, request)); - - // Leak the ping loader, since it will kill itself as soon as it receives a response. - PingLoader* leakedPingLoader = pingLoader.leakPtr(); - UNUSED_PARAM(leakedPingLoader); -} - -PingLoader::PingLoader(Frame* frame, const ResourceRequest& request) - : m_timeout(this, &PingLoader::timeout) -{ - m_handle = ResourceHandle::create(frame->loader()->networkingContext(), request, this, false, false); - - // If the server never responds, FrameLoader won't be able to cancel this load and - // we'll sit here waiting forever. Set a very generous timeout, just in case. - m_timeout.startOneShot(60000); -} - -PingLoader::~PingLoader() -{ - m_handle->cancel(); -} - -} diff --git a/WebCore/loader/PingLoader.h b/WebCore/loader/PingLoader.h deleted file mode 100644 index eb43166..0000000 --- a/WebCore/loader/PingLoader.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 PingLoader_h -#define PingLoader_h - -#include "ResourceHandleClient.h" -#include "Timer.h" -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; -class KURL; -class ResourceError; -class ResourceHandle; -class ResourceResponse; - -// This class triggers asynchronous loads independent of Frame staying alive (i.e., auditing pingbacks). -// Since nothing depends on resources loaded through this class, we just want -// to allow the load to live long enough to ensure the message was actually sent. -// Therefore, as soon as a callback is received from the ResourceHandle, this class -// will cancel the load and delete itself. -class PingLoader : private ResourceHandleClient, public Noncopyable { -public: - static void loadImage(Frame*, const KURL& url); - static void sendPing(Frame*, const KURL& pingURL, const KURL& destinationURL); - - ~PingLoader(); - -private: - PingLoader(Frame*, const ResourceRequest&); - - void didReceiveResponse(ResourceHandle*, const ResourceResponse&) { delete this; } - void didReceiveData(ResourceHandle*, const char*, int) { delete this; } - void didFinishLoading(ResourceHandle*, double) { delete this; } - void didFail(ResourceHandle*, const ResourceError&) { delete this; } - void timeout(Timer<PingLoader>*) { delete this; } - - RefPtr<ResourceHandle> m_handle; - Timer<PingLoader> m_timeout; -}; - -} - -#endif diff --git a/WebCore/loader/PlaceholderDocument.cpp b/WebCore/loader/PlaceholderDocument.cpp deleted file mode 100644 index 93a26db..0000000 --- a/WebCore/loader/PlaceholderDocument.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009 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 "PlaceholderDocument.h" - -namespace WebCore { - -void PlaceholderDocument::attach() -{ - ASSERT(!attached()); - - // Skipping Document::attach(). - ContainerNode::attach(); -} - -} // namespace WebCore diff --git a/WebCore/loader/PlaceholderDocument.h b/WebCore/loader/PlaceholderDocument.h deleted file mode 100644 index 3d40a6e..0000000 --- a/WebCore/loader/PlaceholderDocument.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2009 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 PlaceholderDocument_h -#define PlaceholderDocument_h - -#include "Document.h" - -namespace WebCore { - -class PlaceholderDocument : public Document { -public: - static PassRefPtr<PlaceholderDocument> create(Frame* frame, const KURL& url) - { - return adoptRef(new PlaceholderDocument(frame, url)); - } - - virtual void attach(); - -private: - PlaceholderDocument(Frame* frame, const KURL& url) : Document(frame, url, false, false) { } -}; - -} // namespace WebCore - -#endif // PlaceholderDocument_h diff --git a/WebCore/loader/PolicyCallback.cpp b/WebCore/loader/PolicyCallback.cpp deleted file mode 100644 index 4ec2c84..0000000 --- a/WebCore/loader/PolicyCallback.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "PolicyCallback.h" - -#include "FormState.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "HTMLFormElement.h" - -namespace WebCore { - -PolicyCallback::PolicyCallback() - : m_navigationFunction(0) - , m_newWindowFunction(0) - , m_contentFunction(0) -{ -} - -PolicyCallback::~PolicyCallback() -{ -} - -void PolicyCallback::clear() -{ - clearRequest(); - m_navigationFunction = 0; - m_newWindowFunction = 0; - m_contentFunction = 0; -} - -void PolicyCallback::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 PolicyCallback::set(const ResourceRequest& request, PassRefPtr<FormState> formState, - const String& frameName, const NavigationAction& navigationAction, NewWindowPolicyDecisionFunction function, void* argument) -{ - m_request = request; - m_formState = formState; - m_frameName = frameName; - m_navigationAction = navigationAction; - - m_navigationFunction = 0; - m_newWindowFunction = function; - m_contentFunction = 0; - m_argument = argument; -} - -void PolicyCallback::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 PolicyCallback::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, m_navigationAction, shouldContinue); - ASSERT(!m_contentFunction); -} - -void PolicyCallback::call(PolicyAction action) -{ - ASSERT(!m_navigationFunction); - ASSERT(!m_newWindowFunction); - ASSERT(m_contentFunction); - m_contentFunction(m_argument, action); -} - -void PolicyCallback::clearRequest() -{ - m_request = ResourceRequest(); - m_formState = 0; - m_frameName = String(); -} - -void PolicyCallback::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, m_navigationAction, false); - if (m_contentFunction) - m_contentFunction(m_argument, PolicyIgnore); -} - -} // namespace WebCore diff --git a/WebCore/loader/PolicyCallback.h b/WebCore/loader/PolicyCallback.h deleted file mode 100644 index 415a3e3..0000000 --- a/WebCore/loader/PolicyCallback.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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. - */ - -#ifndef PolicyCallback_h -#define PolicyCallback_h - -#include "FrameLoaderTypes.h" -#include "NavigationAction.h" -#include "ResourceRequest.h" -#include <wtf/RefPtr.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class FormState; - -typedef void (*NavigationPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); -typedef void (*NewWindowPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue); -typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction); - -class PolicyCallback { -public: - PolicyCallback(); - ~PolicyCallback(); - - void clear(); - void set(const ResourceRequest&, PassRefPtr<FormState>, - NavigationPolicyDecisionFunction, void* argument); - void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, - 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; - NavigationAction m_navigationAction; - - NavigationPolicyDecisionFunction m_navigationFunction; - NewWindowPolicyDecisionFunction m_newWindowFunction; - ContentPolicyDecisionFunction m_contentFunction; - void* m_argument; -}; - -} // namespace WebCore - -#endif // PolicyCallback_h diff --git a/WebCore/loader/PolicyChecker.cpp b/WebCore/loader/PolicyChecker.cpp deleted file mode 100644 index 2680386..0000000 --- a/WebCore/loader/PolicyChecker.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "PolicyChecker.h" - -#include "DocumentLoader.h" -#include "FormState.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLFormElement.h" - -namespace WebCore { - -PolicyChecker::PolicyChecker(Frame* frame) - : m_frame(frame) - , m_delegateIsDecidingNavigationPolicy(false) - , m_delegateIsHandlingUnimplementablePolicy(false) - , m_loadType(FrameLoadTypeStandard) -{ -} - -void PolicyChecker::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument) -{ - checkNavigationPolicy(newRequest, m_frame->loader()->activeDocumentLoader(), 0, function, argument); -} - -void PolicyChecker::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_loadType)) - m_loadType = FrameLoadTypeReload; - function(argument, request, 0, true); - return; - } - - loader->setLastCheckedRequest(request); - - m_callback.set(request, formState.get(), function, argument); - - m_delegateIsDecidingNavigationPolicy = true; - m_frame->loader()->client()->dispatchDecidePolicyForNavigationAction(&PolicyChecker::continueAfterNavigationPolicy, - action, request, formState); - m_delegateIsDecidingNavigationPolicy = false; -} - -void PolicyChecker::checkNewWindowPolicy(const NavigationAction& action, NewWindowPolicyDecisionFunction function, - const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, void* argument) -{ - m_callback.set(request, formState, frameName, action, function, argument); - m_frame->loader()->client()->dispatchDecidePolicyForNewWindowAction(&PolicyChecker::continueAfterNewWindowPolicy, - action, request, formState, frameName); -} - -void PolicyChecker::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument) -{ - m_callback.set(function, argument); - m_frame->loader()->client()->dispatchDecidePolicyForMIMEType(&PolicyChecker::continueAfterContentPolicy, - MIMEType, m_frame->loader()->activeDocumentLoader()->request()); -} - -void PolicyChecker::cancelCheck() -{ - m_frame->loader()->client()->cancelPolicyCheck(); - m_callback.clear(); -} - -void PolicyChecker::stopCheck() -{ - m_frame->loader()->client()->cancelPolicyCheck(); - PolicyCallback callback = m_callback; - m_callback.clear(); - callback.cancel(); -} - -void PolicyChecker::cannotShowMIMEType(const ResourceResponse& response) -{ - handleUnimplementablePolicy(m_frame->loader()->client()->cannotShowMIMETypeError(response)); -} - -void PolicyChecker::continueLoadAfterWillSubmitForm(PolicyAction) -{ - // See header file for an explaination of why this function - // isn't like the others. - m_frame->loader()->continueLoadAfterWillSubmitForm(); -} - -void PolicyChecker::continueAfterNavigationPolicy(PolicyAction policy) -{ - PolicyCallback callback = m_callback; - m_callback.clear(); - - bool shouldContinue = policy == PolicyUse; - - switch (policy) { - case PolicyIgnore: - callback.clearRequest(); - break; - case PolicyDownload: - m_frame->loader()->client()->startDownload(callback.request()); - callback.clearRequest(); - break; - case PolicyUse: { - ResourceRequest request(callback.request()); - - if (!m_frame->loader()->client()->canHandleRequest(request)) { - handleUnimplementablePolicy(m_frame->loader()->cannotShowURLError(callback.request())); - callback.clearRequest(); - shouldContinue = false; - } - break; - } - } - - callback.call(shouldContinue); -} - -void PolicyChecker::continueAfterNewWindowPolicy(PolicyAction policy) -{ - PolicyCallback callback = m_callback; - m_callback.clear(); - - switch (policy) { - case PolicyIgnore: - callback.clearRequest(); - break; - case PolicyDownload: - m_frame->loader()->client()->startDownload(callback.request()); - callback.clearRequest(); - break; - case PolicyUse: - break; - } - - callback.call(policy == PolicyUse); -} - -void PolicyChecker::continueAfterContentPolicy(PolicyAction policy) -{ - PolicyCallback callback = m_callback; - m_callback.clear(); - callback.call(policy); -} - -void PolicyChecker::handleUnimplementablePolicy(const ResourceError& error) -{ - m_delegateIsHandlingUnimplementablePolicy = true; - m_frame->loader()->client()->dispatchUnableToImplementPolicy(error); - m_delegateIsHandlingUnimplementablePolicy = false; -} - -} // namespace WebCore diff --git a/WebCore/loader/PolicyChecker.h b/WebCore/loader/PolicyChecker.h deleted file mode 100644 index 541729c..0000000 --- a/WebCore/loader/PolicyChecker.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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. - */ - -#ifndef PolicyChecker_h -#define PolicyChecker_h - -#include "FrameLoaderTypes.h" -#include "PlatformString.h" -#include "PolicyCallback.h" -#include "ResourceRequest.h" -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -class DocumentLoader; -class FormState; -class Frame; -class NavigationAction; -class ResourceError; -class ResourceResponse; - -class PolicyChecker : public Noncopyable { -public: - PolicyChecker(Frame*); - - void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction, void* argument); - void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction, void* argument); - void checkNewWindowPolicy(const NavigationAction&, NewWindowPolicyDecisionFunction, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, void* argument); - void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument); - - // FIXME: These are different. They could use better names. - void cancelCheck(); - void stopCheck(); - - void cannotShowMIMEType(const ResourceResponse&); - - FrameLoadType loadType() const { return m_loadType; } - void setLoadType(FrameLoadType loadType) { m_loadType = loadType; } - - bool delegateIsDecidingNavigationPolicy() const { return m_delegateIsDecidingNavigationPolicy; } - bool delegateIsHandlingUnimplementablePolicy() const { return m_delegateIsHandlingUnimplementablePolicy; } - - // FIXME: This function is a cheat. Basically, this is just an asynchronouc callback - // from the FrameLoaderClient, but this callback uses the policy types and so has to - // live on this object. In the long term, we should create a type for non-policy - // callbacks from the FrameLoaderClient and remove this vestige. I just don't have - // the heart to hack on all the platforms to make that happen right now. - void continueLoadAfterWillSubmitForm(PolicyAction); - -private: - void continueAfterNavigationPolicy(PolicyAction); - void continueAfterNewWindowPolicy(PolicyAction); - void continueAfterContentPolicy(PolicyAction); - - void handleUnimplementablePolicy(const ResourceError&); - - Frame* m_frame; - - bool m_delegateIsDecidingNavigationPolicy; - bool m_delegateIsHandlingUnimplementablePolicy; - - // 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_loadType; - PolicyCallback m_callback; -}; - -} // namespace WebCore - -#endif // PolicyChecker_h diff --git a/WebCore/loader/ProgressTracker.cpp b/WebCore/loader/ProgressTracker.cpp deleted file mode 100644 index cd15433..0000000 --- a/WebCore/loader/ProgressTracker.cpp +++ /dev/null @@ -1,263 +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 "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderStateMachine.h" -#include "FrameLoaderClient.h" -#include "Logging.h" -#include "ResourceResponse.h" -#include <wtf/text/CString.h> -#include <wtf/CurrentTime.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 : Noncopyable { - ProgressItem(long long length) - : bytesReceived(0) - , estimatedLength(length) { } - - long long bytesReceived; - long long estimatedLength; -}; - -unsigned long ProgressTracker::s_uniqueIdentifier = 0; - -ProgressTracker::ProgressTracker() - : 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, "Progress started (%p) - frame %p(\"%s\"), value %f, tracked frames %d, originating frame %p", this, frame, frame->tree()->uniqueName().string().utf8().data(), m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); - - 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, "Progress completed (%p) - frame %p(\"%s\"), value %f, tracked frames %d, originating frame %p", this, frame, frame->tree()->uniqueName().string().utf8().data(), m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); - - 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, "Final progress complete (%p)", this); - - 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, "Progress incremented (%p) - value %f, tracked frames %d, originating frame %p", this, m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); - - 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, adoptPtr(new ProgressItem(estimatedLength)).leakPtr()); -} - -void ProgressTracker::incrementProgress(unsigned long identifier, const char*, int length) -{ - ProgressItem* item = m_progressItems.get(identifier); - - // FIXME: Can this ever happen? - if (!item) - return; - - RefPtr<Frame> frame = m_originatingProgressFrame; - - frame->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 = frame->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; - - // For documents that use WebCore's layout system, treat first layout as the half-way point. - // FIXME: The hasHTMLView function is a sort of roundabout way of asking "do you use WebCore's layout system". - bool useClampedMaxProgress = frame->loader()->client()->hasHTMLView() - && !frame->loader()->stateMachine()->firstLayoutDone(); - double maxProgressValue = useClampedMaxProgress ? 0.5 : finalProgressValue; - 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, "Progress incremented (%p) - value %f, tracked frames %d", this, m_progressValue, m_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; - - frame->loader()->client()->postProgressEstimateChangedNotification(); - - m_lastNotifiedProgressValue = m_progressValue; - m_lastNotifiedProgressTime = now; - } - } - - frame->loader()->client()->didChangeEstimatedProgress(); -} - -void ProgressTracker::completeProgress(unsigned long identifier) -{ - ProgressItem* item = m_progressItems.get(identifier); - - // This can happen if a load fails without receiving any response data. - 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 ++s_uniqueIdentifier; -} - - -} diff --git a/WebCore/loader/ProgressTracker.h b/WebCore/loader/ProgressTracker.h deleted file mode 100644 index 5d5b6b2..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 : public Noncopyable { -public: - ProgressTracker(); - ~ProgressTracker(); - - static 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(); - - static unsigned long s_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/ResourceLoadNotifier.cpp b/WebCore/loader/ResourceLoadNotifier.cpp deleted file mode 100644 index d002ef3..0000000 --- a/WebCore/loader/ResourceLoadNotifier.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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 "ResourceLoadNotifier.h" - -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "InspectorController.h" -#include "Page.h" -#include "ProgressTracker.h" -#include "ResourceLoader.h" - -namespace WebCore { - -ResourceLoadNotifier::ResourceLoadNotifier(Frame* frame) - : m_frame(frame) -{ -} - -void ResourceLoadNotifier::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_frame->loader()->client()->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - -void ResourceLoadNotifier::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_frame->loader()->client()->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - -void ResourceLoadNotifier::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse) -{ - m_frame->loader()->applyUserAgent(clientRequest); - - dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse); -} - -void ResourceLoadNotifier::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r) -{ - loader->documentLoader()->addResponse(r); - - if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), r); - - dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r); -} - -void ResourceLoadNotifier::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 ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader, double finishTime) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - dispatchDidFinishLoading(loader->documentLoader(), loader->identifier(), finishTime); -} - -void ResourceLoadNotifier::didFailToLoad(ResourceLoader* loader, const ResourceError& error) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - - if (!error.isNull()) - m_frame->loader()->client()->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didFailLoading(loader->identifier(), error); -#endif -} - -void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) -{ - m_frame->loader()->client()->assignIdentifierToInitialRequest(identifier, loader, request); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->identifierForInitialRequest(identifier, loader, request); -#endif -} - -void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - StringImpl* oldRequestURL = request.url().string().impl(); - m_frame->loader()->documentLoader()->didTellClientAboutLoad(request.url()); - - m_frame->loader()->client()->dispatchWillSendRequest(loader, identifier, request, redirectResponse); - - // If the URL changed, then we want to put that new URL in the "did tell client" set too. - if (!request.isNull() && oldRequestURL != request.url().string().impl()) - m_frame->loader()->documentLoader()->didTellClientAboutLoad(request.url()); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->willSendRequest(identifier, request, redirectResponse); -#endif -} - -void ResourceLoadNotifier::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r) -{ - m_frame->loader()->client()->dispatchDidReceiveResponse(loader, identifier, r); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveResponse(identifier, loader, r); -#endif -} - -void ResourceLoadNotifier::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) -{ - m_frame->loader()->client()->dispatchDidReceiveContentLength(loader, identifier, length); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveContentLength(identifier, length); -#endif -} - -void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier, double finishTime) -{ - m_frame->loader()->client()->dispatchDidFinishLoading(loader, identifier); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didFinishLoading(identifier, finishTime); -#endif -} - -void ResourceLoadNotifier::dispatchTransferLoadingResourceFromPage(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request, Page* oldPage) -{ - ASSERT(oldPage != m_frame->page()); - m_frame->loader()->client()->transferLoadingResourceFromPage(identifier, loader, request, oldPage); - - oldPage->progress()->completeProgress(identifier); -} - -void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error) -{ - if (!response.isNull()) - dispatchDidReceiveResponse(loader, identifier, response); - - if (length > 0) - dispatchDidReceiveContentLength(loader, identifier, length); - - if (error.isNull()) - dispatchDidFinishLoading(loader, identifier, 0); - else - m_frame->loader()->client()->dispatchDidFailLoading(loader, identifier, error); -} - -} // namespace WebCore diff --git a/WebCore/loader/ResourceLoadNotifier.h b/WebCore/loader/ResourceLoadNotifier.h deleted file mode 100644 index 2f10856..0000000 --- a/WebCore/loader/ResourceLoadNotifier.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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. - */ - -#ifndef ResourceLoadNotifier_h -#define ResourceLoadNotifier_h - -#include <wtf/Noncopyable.h> - -namespace WebCore { - -class AuthenticationChallenge; -class DocumentLoader; -class Frame; -class Page; -class ResourceError; -class ResourceLoader; -class ResourceResponse; -class ResourceRequest; - -class ResourceLoadNotifier : public Noncopyable { -public: - ResourceLoadNotifier(Frame*); - - void didReceiveAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - void didCancelAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - - void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); - void didReceiveResponse(ResourceLoader*, const ResourceResponse&); - void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived); - void didFinishLoad(ResourceLoader*, double finishTime); - void didFailToLoad(ResourceLoader*, const ResourceError&); - - void assignIdentifierToInitialRequest(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, double finishTime); - void dispatchTransferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*); - - void sendRemainingDelegateMessages(DocumentLoader*, unsigned long identifier, const ResourceResponse&, int length, const ResourceError&); - -private: - Frame* m_frame; -}; - -} // namespace WebCore - -#endif // ResourceLoadNotifier_h diff --git a/WebCore/loader/ResourceLoadPriority.h b/WebCore/loader/ResourceLoadPriority.h deleted file mode 100644 index 1c9d5d2..0000000 --- a/WebCore/loader/ResourceLoadPriority.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010 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. 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 INC. 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 ResourceLoadPriority_h -#define ResourceLoadPriority_h - -namespace WebCore { - -enum ResourceLoadPriority { - ResourceLoadPriorityVeryLow, - ResourceLoadPriorityLow, - ResourceLoadPriorityMedium, - ResourceLoadPriorityHigh, - ResourceLoadPriorityLowest = ResourceLoadPriorityVeryLow, - ResourceLoadPriorityHighest = ResourceLoadPriorityHigh, - // The unresolved priority is here for the convenience of the clients. It should not be passed to the ResourceLoadScheduler. - ResourceLoadPriorityUnresolved, -}; - -} - -#endif - diff --git a/WebCore/loader/ResourceLoadScheduler.cpp b/WebCore/loader/ResourceLoadScheduler.cpp deleted file mode 100644 index 8cf2c18..0000000 --- a/WebCore/loader/ResourceLoadScheduler.cpp +++ /dev/null @@ -1,289 +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. - Copyright (C) 2010 Google 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 "ResourceLoadScheduler.h" - -#include "Document.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "InspectorInstrumentation.h" -#include "KURL.h" -#include "Logging.h" -#include "NetscapePlugInStreamLoader.h" -#include "ResourceLoader.h" -#include "ResourceRequest.h" -#include "SubresourceLoader.h" -#include <wtf/text/CString.h> - -#define REQUEST_MANAGEMENT_ENABLED 1 - -namespace WebCore { - -#if REQUEST_MANAGEMENT_ENABLED -static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20; -// Match the parallel connection count used by the networking layer. -static unsigned maxRequestsInFlightPerHost; -#else -static const unsigned maxRequestsInFlightForNonHTTPProtocols = 10000; -static const unsigned maxRequestsInFlightPerHost = 10000; -#endif - -ResourceLoadScheduler::HostInformation* ResourceLoadScheduler::hostForURL(const KURL& url, CreateHostPolicy createHostPolicy) -{ - if (!url.protocolInHTTPFamily()) - return m_nonHTTPProtocolHost; - - m_hosts.checkConsistency(); - String hostName = url.host(); - HostInformation* host = m_hosts.get(hostName); - if (!host && createHostPolicy == CreateIfNotFound) { - host = new HostInformation(hostName, maxRequestsInFlightPerHost); - m_hosts.add(hostName, host); - } - return host; -} - -ResourceLoadScheduler* resourceLoadScheduler() -{ - ASSERT(isMainThread()); - DEFINE_STATIC_LOCAL(ResourceLoadScheduler, resourceLoadScheduler, ()); - return &resourceLoadScheduler; -} - -ResourceLoadScheduler::ResourceLoadScheduler() - : m_nonHTTPProtocolHost(new HostInformation(String(), maxRequestsInFlightForNonHTTPProtocols)) - , m_requestTimer(this, &ResourceLoadScheduler::requestTimerFired) - , m_isSuspendingPendingRequests(false) - , m_isSerialLoadingEnabled(false) -{ -#if REQUEST_MANAGEMENT_ENABLED - maxRequestsInFlightPerHost = initializeMaximumHTTPConnectionCountPerHost(); -#endif -} - -PassRefPtr<SubresourceLoader> ResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, ResourceLoadPriority priority, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff) -{ - PassRefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, client, request, securityCheck, sendResourceLoadCallbacks, shouldContentSniff); - if (loader) - scheduleLoad(loader.get(), priority); - return loader; -} - -PassRefPtr<NetscapePlugInStreamLoader> ResourceLoadScheduler::schedulePluginStreamLoad(Frame* frame, NetscapePlugInStreamLoaderClient* client, const ResourceRequest& request) -{ - PassRefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request); - if (loader) - scheduleLoad(loader.get(), ResourceLoadPriorityLow); - return loader; -} - -void ResourceLoadScheduler::addMainResourceLoad(ResourceLoader* resourceLoader) -{ - hostForURL(resourceLoader->url(), CreateIfNotFound)->addLoadInProgress(resourceLoader); -} - -void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, ResourceLoadPriority priority) -{ - ASSERT(resourceLoader); - ASSERT(priority != ResourceLoadPriorityUnresolved); -#if !REQUEST_MANAGEMENT_ENABLED - priority = ResourceLoadPriorityHighest; -#endif - - LOG(ResourceLoading, "ResourceLoadScheduler::load resource %p '%s'", resourceLoader, resourceLoader->url().string().latin1().data()); - HostInformation* host = hostForURL(resourceLoader->url(), CreateIfNotFound); - bool hadRequests = host->hasRequests(); - host->schedule(resourceLoader, priority); - - if (priority > ResourceLoadPriorityLow || !resourceLoader->url().protocolInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) { - // Try to request important resources immediately. - servePendingRequests(host, priority); - } else { - // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones. - InspectorInstrumentation::didScheduleResourceRequest(resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame()->document() : 0, resourceLoader->url()); - scheduleServePendingRequests(); - } -} - -void ResourceLoadScheduler::remove(ResourceLoader* resourceLoader) -{ - ASSERT(resourceLoader); - - HostInformation* host = hostForURL(resourceLoader->url()); - if (host) - host->remove(resourceLoader); - scheduleServePendingRequests(); -} - -void ResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resourceLoader, const KURL& redirectURL) -{ - HostInformation* oldHost = hostForURL(resourceLoader->url()); - ASSERT(oldHost); - HostInformation* newHost = hostForURL(redirectURL, CreateIfNotFound); - - if (oldHost->name() == newHost->name()) - return; - - newHost->addLoadInProgress(resourceLoader); - oldHost->remove(resourceLoader); -} - -void ResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority) -{ - LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests. m_isSuspendingPendingRequests=%d", m_isSuspendingPendingRequests); - if (m_isSuspendingPendingRequests) - return; - - m_requestTimer.stop(); - - servePendingRequests(m_nonHTTPProtocolHost, minimumPriority); - - Vector<HostInformation*> hostsToServe; - m_hosts.checkConsistency(); - HostMap::iterator end = m_hosts.end(); - for (HostMap::iterator iter = m_hosts.begin(); iter != end; ++iter) - hostsToServe.append(iter->second); - - int size = hostsToServe.size(); - for (int i = 0; i < size; ++i) { - HostInformation* host = hostsToServe[i]; - if (host->hasRequests()) - servePendingRequests(host, minimumPriority); - else - delete m_hosts.take(host->name()); - } -} - -void ResourceLoadScheduler::servePendingRequests(HostInformation* host, ResourceLoadPriority minimumPriority) -{ - LOG(ResourceLoading, "ResourceLoadScheduler::servePendingRequests HostInformation.m_name='%s'", host->name().latin1().data()); - - for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) { - HostInformation::RequestQueue& requestsPending = host->requestsPending((ResourceLoadPriority) priority); - - while (!requestsPending.isEmpty()) { - RefPtr<ResourceLoader> resourceLoader = requestsPending.first(); - - // For named hosts - which are only http(s) hosts - we should always enforce the connection limit. - // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing - // and we don't know all stylesheets yet. - Document* document = resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame()->document() : 0; - bool shouldLimitRequests = !host->name().isNull() || (document && (document->parsing() || !document->haveStylesheetsLoaded())); - if (shouldLimitRequests && host->limitRequests()) - return; - - requestsPending.removeFirst(); - host->addLoadInProgress(resourceLoader.get()); - resourceLoader->start(); - } - } -} - -void ResourceLoadScheduler::suspendPendingRequests() -{ - ASSERT(!m_isSuspendingPendingRequests); - m_isSuspendingPendingRequests = true; -} - -void ResourceLoadScheduler::resumePendingRequests() -{ - ASSERT(m_isSuspendingPendingRequests); - m_isSuspendingPendingRequests = false; - if (!m_hosts.isEmpty() || m_nonHTTPProtocolHost->hasRequests()) - scheduleServePendingRequests(); -} - -void ResourceLoadScheduler::scheduleServePendingRequests() -{ - LOG(ResourceLoading, "ResourceLoadScheduler::scheduleServePendingRequests, m_requestTimer.isActive()=%u", m_requestTimer.isActive()); - if (!m_requestTimer.isActive()) - m_requestTimer.startOneShot(0); -} - -void ResourceLoadScheduler::requestTimerFired(Timer<ResourceLoadScheduler>*) -{ - LOG(ResourceLoading, "ResourceLoadScheduler::requestTimerFired\n"); - servePendingRequests(); -} - -ResourceLoadScheduler::HostInformation::HostInformation(const String& name, unsigned maxRequestsInFlight) - : m_name(name) - , m_maxRequestsInFlight(maxRequestsInFlight) -{ -} - -ResourceLoadScheduler::HostInformation::~HostInformation() -{ - ASSERT(m_requestsLoading.isEmpty()); - for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) - ASSERT(m_requestsPending[p].isEmpty()); -} - -void ResourceLoadScheduler::HostInformation::schedule(ResourceLoader* resourceLoader, ResourceLoadPriority priority) -{ - m_requestsPending[priority].append(resourceLoader); -} - -void ResourceLoadScheduler::HostInformation::addLoadInProgress(ResourceLoader* resourceLoader) -{ - LOG(ResourceLoading, "HostInformation '%s' loading '%s'. Current count %d", m_name.latin1().data(), resourceLoader->url().string().latin1().data(), m_requestsLoading.size()); - m_requestsLoading.add(resourceLoader); -} - -void ResourceLoadScheduler::HostInformation::remove(ResourceLoader* resourceLoader) -{ - if (m_requestsLoading.contains(resourceLoader)) { - m_requestsLoading.remove(resourceLoader); - return; - } - - for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) { - RequestQueue::iterator end = m_requestsPending[priority].end(); - for (RequestQueue::iterator it = m_requestsPending[priority].begin(); it != end; ++it) { - if (*it == resourceLoader) { - m_requestsPending[priority].remove(it); - return; - } - } - } -} - -bool ResourceLoadScheduler::HostInformation::hasRequests() const -{ - if (!m_requestsLoading.isEmpty()) - return true; - for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) { - if (!m_requestsPending[p].isEmpty()) - return true; - } - return false; -} - -bool ResourceLoadScheduler::HostInformation::limitRequests() const -{ - return m_requestsLoading.size() >= (resourceLoadScheduler()->isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight); -} - -} // namespace WebCore diff --git a/WebCore/loader/ResourceLoadScheduler.h b/WebCore/loader/ResourceLoadScheduler.h deleted file mode 100644 index 163b67e..0000000 --- a/WebCore/loader/ResourceLoadScheduler.h +++ /dev/null @@ -1,117 +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. - Copyright (C) 2010 Google 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 ResourceLoadScheduler_h -#define ResourceLoadScheduler_h - -#include "FrameLoaderTypes.h" -#include "PlatformString.h" -#include "ResourceLoadPriority.h" -#include "Timer.h" -#include <wtf/Deque.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class Frame; -class KURL; -class NetscapePlugInStreamLoader; -class NetscapePlugInStreamLoaderClient; -class ResourceLoader; -class ResourceRequest; -class SubresourceLoader; -class SubresourceLoaderClient; - -class ResourceLoadScheduler : public Noncopyable { -public: - friend ResourceLoadScheduler* resourceLoadScheduler(); - - PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, SubresourceLoaderClient*, const ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityLow, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true); - PassRefPtr<NetscapePlugInStreamLoader> schedulePluginStreamLoad(Frame*, NetscapePlugInStreamLoaderClient*, const ResourceRequest&); - void addMainResourceLoad(ResourceLoader*); - void remove(ResourceLoader*); - void crossOriginRedirectReceived(ResourceLoader*, const KURL& redirectURL); - - void servePendingRequests(ResourceLoadPriority minimumPriority = ResourceLoadPriorityVeryLow); - void suspendPendingRequests(); - void resumePendingRequests(); - - bool isSerialLoadingEnabled() const { return m_isSerialLoadingEnabled; } - void setSerialLoadingEnabled(bool b) { m_isSerialLoadingEnabled = b; } - -private: - ResourceLoadScheduler(); - ~ResourceLoadScheduler(); - - void scheduleLoad(ResourceLoader*, ResourceLoadPriority); - void scheduleServePendingRequests(); - void requestTimerFired(Timer<ResourceLoadScheduler>*); - - class HostInformation : public Noncopyable { - public: - HostInformation(const String&, unsigned); - ~HostInformation(); - - const String& name() const { return m_name; } - void schedule(ResourceLoader*, ResourceLoadPriority = ResourceLoadPriorityVeryLow); - void addLoadInProgress(ResourceLoader*); - void remove(ResourceLoader*); - bool hasRequests() const; - bool limitRequests() const; - - typedef Deque<RefPtr<ResourceLoader> > RequestQueue; - RequestQueue& requestsPending(ResourceLoadPriority priority) { return m_requestsPending[priority]; } - - private: - RequestQueue m_requestsPending[ResourceLoadPriorityHighest + 1]; - typedef HashSet<RefPtr<ResourceLoader> > RequestMap; - RequestMap m_requestsLoading; - const String m_name; - const int m_maxRequestsInFlight; - }; - - enum CreateHostPolicy { - CreateIfNotFound, - FindOnly - }; - - HostInformation* hostForURL(const KURL&, CreateHostPolicy = FindOnly); - void servePendingRequests(HostInformation*, ResourceLoadPriority); - - typedef HashMap<String, HostInformation*, StringHash> HostMap; - HostMap m_hosts; - HostInformation* m_nonHTTPProtocolHost; - - Timer<ResourceLoadScheduler> m_requestTimer; - - bool m_isSuspendingPendingRequests; - bool m_isSerialLoadingEnabled; -}; - -ResourceLoadScheduler* resourceLoadScheduler(); - -} - -#endif diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp deleted file mode 100644 index bc56000..0000000 --- a/WebCore/loader/ResourceLoader.cpp +++ /dev/null @@ -1,527 +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 "ApplicationCacheHost.h" -#include "DocumentLoader.h" -#include "FileStreamProxy.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "InspectorInstrumentation.h" -#include "Page.h" -#include "ProgressTracker.h" -#include "ResourceError.h" -#include "ResourceHandle.h" -#include "ResourceLoadScheduler.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()) -{ -} - -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; - - resourceLoadScheduler()->remove(this); - - if (m_handle) { - // Clear out the ResourceHandle's client so that it doesn't try to call - // us back after we release it, unless it has been replaced by someone else. - if (m_handle->client() == this) - m_handle->setClient(0); - m_handle = 0; - } - - m_resourceData = 0; - m_deferredRequest = ResourceRequest(); -} - -bool ResourceLoader::init(const ResourceRequest& r) -{ - ASSERT(!m_handle); - ASSERT(m_request.isNull()); - ASSERT(m_deferredRequest.isNull()); - ASSERT(!m_documentLoader->isSubstituteLoadPending(this)); - - ResourceRequest clientRequest(r); - - // https://bugs.webkit.org/show_bug.cgi?id=26391 - // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests - // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets - // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that - // method, we need to make sure there is always a 1st party for cookies set. - if (clientRequest.firstPartyForCookies().isNull()) { - if (Document* document = m_frame->document()) - clientRequest.setFirstPartyForCookies(document->firstPartyForCookies()); - } - - m_request = clientRequest; - - willSendRequest(m_request, ResourceResponse()); - if (m_request.isNull()) { - didFail(frameLoader()->cancelledError(m_request)); - return false; - } - - return true; -} - -void ResourceLoader::start() -{ - ASSERT(!m_handle); - ASSERT(!m_request.isNull()); - ASSERT(m_deferredRequest.isNull()); - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - if (m_documentLoader->scheduleArchiveLoad(this, m_request, m_request.url())) - return; -#endif - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url())) - return; -#endif - - if (m_defersLoading) { - m_deferredRequest = m_request; - return; - } - - if (!m_reachedTerminalState) - m_handle = ResourceHandle::create(m_frame->loader()->networkingContext(), m_request, this, m_defersLoading, m_shouldContentSniff); -} - -void ResourceLoader::setDefersLoading(bool defers) -{ - m_defersLoading = defers; - if (m_handle) - m_handle->setDefersLoading(defers); - if (!defers && !m_deferredRequest.isNull()) { - m_request = m_deferredRequest; - m_deferredRequest = ResourceRequest(); - start(); - } -} - -#if PLATFORM(ANDROID) -// TODO: This needs upstreaming to WebKit. -void ResourceLoader::pauseLoad(bool pause) -{ - if (m_handle) - m_handle->pauseLoad(pause); -} -#endif - -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()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request); - } - - frameLoader()->notifier()->willSendRequest(this, request, redirectResponse); - } - - if (!redirectResponse.isNull()) - resourceLoadScheduler()->crossOriginRedirectReceived(this, request.url()); - m_request = request; -} - -void ResourceLoader::didSendData(unsigned long long, unsigned long long) -{ -} - -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()->notifier()->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()->notifier()->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(double finishTime) -{ - // 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(finishTime); - releaseResources(); -} - -void ResourceLoader::didFinishLoadingOnePart(double finishTime) -{ - if (m_cancelled) - return; - ASSERT(!m_reachedTerminalState); - - if (m_calledDidFinishLoad) - return; - m_calledDidFinishLoad = true; - if (m_sendResourceLoadCallbacks) - frameLoader()->notifier()->didFinishLoad(this, finishTime); -} - -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()->notifier()->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. Canceling 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_identifier && !m_calledDidFinishLoad) - frameLoader()->notifier()->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) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse)) - return; -#endif - 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) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response)) - return; -#endif - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceResponse(m_frame.get(), identifier(), response); - didReceiveResponse(response); - InspectorInstrumentation::didReceiveResourceResponse(cookie); -} - -void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived) -{ - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceData(m_frame.get(), identifier()); - didReceiveData(data, length, lengthReceived, false); - InspectorInstrumentation::didReceiveResourceData(cookie); -} - -void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime) -{ - didFinishLoading(finishTime); -} - -void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error) -{ -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error)) - return; -#endif - didFail(error); -} - -void ResourceLoader::wasBlocked(ResourceHandle*) -{ - didFail(blockedError()); -} - -void ResourceLoader::cannotShowURL(ResourceHandle*) -{ - didFail(cannotShowURLError()); -} - -bool ResourceLoader::shouldUseCredentialStorage() -{ - RefPtr<ResourceLoader> protector(this); - return frameLoader()->shouldUseCredentialStorage(this); -} - -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()->notifier()->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()->notifier()->didCancelAuthenticationChallenge(this, challenge); -} - -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) -bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) -{ - RefPtr<ResourceLoader> protector(this); - return frameLoader()->canAuthenticateAgainstProtectionSpace(this, protectionSpace); -} -#endif - -void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) -{ - cancel(); -} - -void ResourceLoader::willCacheResponse(ResourceHandle*, CacheStoragePolicy& policy) -{ - // <rdar://problem/7249553> - There are reports of crashes with this method being called - // with a null m_frame->settings(), which can only happen if the frame doesn't have a page. - // Sadly we have no reproducible cases of this. - // We think that any frame without a page shouldn't have any loads happening in it, yet - // there is at least one code path where that is not true. - ASSERT(m_frame->settings()); - - // When in private browsing mode, prevent caching to disk - if (policy == StorageAllowed && m_frame->settings() && m_frame->settings()->privateBrowsingEnabled()) - policy = StorageAllowedInMemoryOnly; -} - -#if ENABLE(BLOB) -AsyncFileStream* ResourceLoader::createAsyncFileStream(FileStreamClient* client) -{ - // It is OK to simply return a pointer since FileStreamProxy::create adds an extra ref. - return FileStreamProxy::create(m_frame->document()->scriptExecutionContext(), client).get(); -} -#endif - -} diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h deleted file mode 100644 index e5c5d3f..0000000 --- a/WebCore/loader/ResourceLoader.h +++ /dev/null @@ -1,179 +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 ApplicationCacheHost; - class DocumentLoader; - class Frame; - class FrameLoader; - class ProtectionSpace; - class ResourceHandle; - class SharedBuffer; - - class ResourceLoader : public RefCounted<ResourceLoader>, protected ResourceHandleClient { - public: - virtual ~ResourceLoader(); - - void cancel(); - - virtual bool init(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); -#if PLATFORM(ANDROID) -// TODO: This needs upstreaming to WebKit. - virtual void pauseLoad(bool); -#endif - - 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); - virtual void didReceiveCachedMetadata(const char*, int) { } - void willStopBufferingData(const char*, int); - virtual void didFinishLoading(double finishTime); - virtual void didFail(const ResourceError&); - - virtual bool shouldUseCredentialStorage(); - virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); - void didCancelAuthenticationChallenge(const AuthenticationChallenge&); -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - virtual bool canAuthenticateAgainstProtectionSpace(const ProtectionSpace&); -#endif - 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 didReceiveCachedMetadata(ResourceHandle*, const char* data, int length) { didReceiveCachedMetadata(data, length); } - virtual void didFinishLoading(ResourceHandle*, double finishTime); - 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 bool shouldUseCredentialStorage(ResourceHandle*) { return shouldUseCredentialStorage(); } - virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didReceiveAuthenticationChallenge(challenge); } - virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge& challenge) { didCancelAuthenticationChallenge(challenge); } -#if USE(PROTECTION_SPACE_AUTH_CALLBACK) - virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace& protectionSpace) { return canAuthenticateAgainstProtectionSpace(protectionSpace); } -#endif - virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge& challenge) { receivedCancellation(challenge); } - virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&); -#if PLATFORM(MAC) - virtual NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse*); -#endif -#if USE(CFNETWORK) - virtual bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef); -#endif -#if ENABLE(BLOB) - virtual AsyncFileStream* createAsyncFileStream(FileStreamClient*); -#endif - - const KURL& url() const { return m_request.url(); } - ResourceHandle* handle() const { return m_handle.get(); } - bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } - - bool reachedTerminalState() const { return m_reachedTerminalState; } - - void setShouldBufferData(bool shouldBufferData); - - protected: - ResourceLoader(Frame*, bool sendResourceLoadCallbacks, bool shouldContentSniff); - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - friend class ApplicationCacheHost; // for access to request() -#endif - friend class ResourceLoadScheduler; // for access to start() - // start() actually sends the load to the network (unless the load is being - // deferred) and should only be called by ResourceLoadScheduler or setDefersLoading(). - void start(); - - virtual void didCancel(const ResourceError&); - void didFinishLoadingOnePart(double finishTime); - - const ResourceRequest& request() const { return m_request; } - 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; - ResourceRequest m_deferredRequest; - }; - -} - -#endif diff --git a/WebCore/loader/SinkDocument.cpp b/WebCore/loader/SinkDocument.cpp deleted file mode 100644 index 47535dc..0000000 --- a/WebCore/loader/SinkDocument.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2010 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 "SinkDocument.h" - -#include "RawDataDocumentParser.h" - -namespace WebCore { - -class SinkDocumentParser : public RawDataDocumentParser { -public: - static PassRefPtr<SinkDocumentParser> create(SinkDocument* document) - { - return adoptRef(new SinkDocumentParser(document)); - } - -private: - SinkDocumentParser(SinkDocument* document) - : RawDataDocumentParser(document) - { - } - - // Ignore all data. - virtual void appendBytes(DocumentWriter*, const char*, int, bool) { } -}; - -SinkDocument::SinkDocument(Frame* frame, const KURL& url) - : HTMLDocument(frame, url) -{ - setCompatibilityMode(QuirksMode); - lockCompatibilityMode(); -} - -PassRefPtr<DocumentParser> SinkDocument::createParser() -{ - return SinkDocumentParser::create(this); -} - -} // namespace WebCore diff --git a/WebCore/loader/SinkDocument.h b/WebCore/loader/SinkDocument.h deleted file mode 100644 index 50152ff..0000000 --- a/WebCore/loader/SinkDocument.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2010 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 SinkDocument_h -#define SinkDocument_h - -#include "HTMLDocument.h" - -namespace WebCore { - -class SinkDocument : public HTMLDocument { -public: - static PassRefPtr<SinkDocument> create(Frame* frame, const KURL& url) - { - return adoptRef(new SinkDocument(frame, url)); - } - -private: - SinkDocument(Frame*, const KURL&); - - virtual PassRefPtr<DocumentParser> createParser(); -}; - - -}; // namespace WebCore - -#endif // SinkDocument_h diff --git a/WebCore/loader/SubframeLoader.cpp b/WebCore/loader/SubframeLoader.cpp deleted file mode 100644 index dd2b8de..0000000 --- a/WebCore/loader/SubframeLoader.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) 2008 Alp Toker <alp@atoker.com> - * Copyright (C) Research In Motion Limited 2009. 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 "SubframeLoader.h" - -#include "Frame.h" -#include "FrameLoaderClient.h" -#include "HTMLAppletElement.h" -#include "HTMLFrameElementBase.h" -#include "HTMLNames.h" -#include "HTMLPlugInImageElement.h" -#include "MIMETypeRegistry.h" -#include "Page.h" -#include "PluginData.h" -#include "PluginDocument.h" -#include "RenderEmbeddedObject.h" -#include "RenderView.h" -#include "Settings.h" -#include "XSSAuditor.h" - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -#include "HTMLMediaElement.h" -#include "RenderVideo.h" -#endif - -namespace WebCore { - -using namespace HTMLNames; - -SubframeLoader::SubframeLoader(Frame* frame) - : m_containsPlugins(false) - , m_frame(frame) -{ -} - -void SubframeLoader::clear() -{ - m_containsPlugins = false; -} - -bool SubframeLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) -{ - // Support for <frame src="javascript:string"> - KURL scriptURL; - KURL url; - if (protocolIsJavaScript(urlString)) { - scriptURL = completeURL(urlString); // completeURL() encodes the URL. - url = blankURL(); - } else - url = completeURL(urlString); - - Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList); - if (!frame) - return false; - - if (!scriptURL.isEmpty()) - frame->script()->executeIfJavaScriptURL(scriptURL); - - return true; -} - -bool SubframeLoader::resourceWillUsePlugin(const String& url, const String& mimeType) -{ - KURL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - bool useFallback; - return shouldUsePlugin(completedURL, mimeType, false, useFallback); -} - -bool SubframeLoader::requestObject(HTMLPlugInImageElement* ownerElement, 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 (!m_frame->script()->xssAuditor()->canLoadObject(url)) { - // It is unsafe to honor the request for this object. - return false; - } - - // FIXME: None of this code should use renderers! - RenderEmbeddedObject* renderer = ownerElement->renderEmbeddedObject(); - ASSERT(renderer); - if (!renderer) - return false; - - KURL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - - bool useFallback; - if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) { - Settings* settings = m_frame->settings(); - if ((!allowPlugins(AboutToInstantiatePlugin) - // Application plugins are plugins implemented by the user agent, for example Qt plugins, - // as opposed to third-party code such as flash. The user agent decides whether or not they are - // permitted, rather than WebKit. - && !MIMETypeRegistry::isApplicationPluginMIMEType(mimeType)) - || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType))) - return false; - if (m_frame->document() && m_frame->document()->securityOrigin()->isSandboxed(SandboxPlugins)) - return false; - - ASSERT(ownerElement->hasTagName(objectTag) || ownerElement->hasTagName(embedTag)); - HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(ownerElement); - - return loadPlugin(pluginElement, completedURL, mimeType, paramNames, paramValues, useFallback); - } - - // If the plug-in element already contains a subframe, loadOrRedirectSubframe will re-use it. Otherwise, - // it will create a new frame and set it as the RenderPart's widget, causing what was previously - // in the widget to be torn down. - return loadOrRedirectSubframe(ownerElement, completedURL, frameName, true, true); -} - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -PassRefPtr<Widget> SubframeLoader::loadMediaPlayerProxyPlugin(Node* node, const KURL& url, - const Vector<String>& paramNames, const Vector<String>& paramValues) -{ - ASSERT(node->hasTagName(videoTag) || node->hasTagName(audioTag)); - - if (!m_frame->script()->xssAuditor()->canLoadObject(url.string())) - return 0; - - KURL completedURL; - if (!url.isEmpty()) - completedURL = completeURL(url); - - if (!m_frame->document()->securityOrigin()->canDisplay(completedURL)) { - FrameLoader::reportLocalLoadFailed(m_frame, completedURL.string()); - return 0; - } - - HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); - RenderPart* renderer = toRenderPart(node->renderer()); - IntSize size; - - if (renderer) - size = IntSize(renderer->contentWidth(), renderer->contentHeight()); - else if (mediaElement->isVideo()) - size = RenderVideo::defaultSize(); - - m_frame->loader()->checkIfRunInsecureContent(m_frame->document()->securityOrigin(), completedURL); - - RefPtr<Widget> widget = m_frame->loader()->client()->createMediaPlayerProxyPlugin(size, mediaElement, completedURL, - paramNames, paramValues, "application/x-media-element-proxy-plugin"); - - if (widget && renderer) { - renderer->setWidget(widget); - renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); - } - m_containsPlugins = true; - - return widget ? widget.release() : 0; -} - -void FrameLoader::hideMediaPlayerProxyPlugin(Widget* widget) -{ - m_client->hideMediaPlayerProxyPlugin(widget); -} - -void FrameLoader::showMediaPlayerProxyPlugin(Widget* widget) -{ - m_client->showMediaPlayerProxyPlugin(widget); -} - -#endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) - -PassRefPtr<Widget> SubframeLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args) -{ - String baseURLString; - String codeBaseURLString; - 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; - else if (equalIgnoringCase(it->first, "codebase")) - codeBaseURLString = it->second; - paramNames.append(it->first); - paramValues.append(it->second); - } - - if (!codeBaseURLString.isEmpty()) { - KURL codeBaseURL = completeURL(codeBaseURLString); - if (!element->document()->securityOrigin()->canDisplay(codeBaseURL)) { - FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string()); - return 0; - } - } - - if (baseURLString.isEmpty()) - baseURLString = m_frame->document()->baseURL().string(); - KURL baseURL = completeURL(baseURLString); - - RefPtr<Widget> widget; - if (allowPlugins(AboutToInstantiatePlugin)) - widget = m_frame->loader()->client()->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues); - if (!widget) - return 0; - - m_containsPlugins = true; - return widget; -} - -Frame* SubframeLoader::loadOrRedirectSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList) -{ - Frame* frame = ownerElement->contentFrame(); - if (frame) - frame->navigationScheduler()->scheduleLocationChange(m_frame->document()->securityOrigin(), url.string(), m_frame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList); - else - frame = loadSubframe(ownerElement, url, frameName, m_frame->loader()->outgoingReferrer()); - return frame; -} - -Frame* SubframeLoader::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 (!ownerElement->document()->securityOrigin()->canDisplay(url)) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return 0; - } - - bool hideReferrer = SecurityOrigin::shouldHideReferrer(url, referrer); - RefPtr<Frame> frame = m_frame->loader()->client()->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight); - - if (!frame) { - m_frame->loader()->checkCallImplicitClose(); - return 0; - } - - // All new frames will have m_isComplete set to true at this point due to synchronously loading - // an empty document in FrameLoader::init(). But many frames will now be starting an - // asynchronous load of url, so we set m_isComplete to false and then check if the load is - // actually completed below. (Note that we set m_isComplete to false even for synchronous - // loads, so that checkCompleted() below won't bail early.) - // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed. - frame->loader()->started(); - - RenderObject* renderer = ownerElement->renderer(); - FrameView* view = frame->view(); - if (renderer && renderer->isWidget() && view) - toRenderWidget(renderer)->setWidget(view); - - m_frame->loader()->checkCallImplicitClose(); - - // Some loads are performed synchronously (e.g., about:blank and loads - // cancelled by returning a null ResourceRequest from requestFromDelegate). - // 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 and mark the load as being - // complete. - // 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 (frame->loader()->state() == FrameStateComplete && !frame->loader()->policyDocumentLoader()) - frame->loader()->checkCompleted(); - - return frame.get(); -} - -bool SubframeLoader::allowPlugins(ReasonForCallingAllowPlugins reason) -{ - Settings* settings = m_frame->settings(); - bool allowed = m_frame->loader()->client()->allowPlugins(settings && settings->arePluginsEnabled()); - if (!allowed && reason == AboutToInstantiatePlugin) - m_frame->loader()->client()->didNotAllowPlugins(); - return allowed; -} - -bool SubframeLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback) -{ - if (m_frame->loader()->client()->shouldUsePluginDocument(mimeType)) { - useFallback = false; - return true; - } - - // 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")) { - const PluginData* pluginData = m_frame->page()->pluginData(); - String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String(); - if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false)) - return true; - } - - ObjectContentType objectType = m_frame->loader()->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; -} - -Document* SubframeLoader::document() const -{ - return m_frame->document(); -} - -bool SubframeLoader::loadPlugin(HTMLPlugInImageElement* pluginElement, const KURL& url, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback) -{ - RenderEmbeddedObject* renderer = pluginElement->renderEmbeddedObject(); - - // FIXME: This code should not depend on renderer! - if (!renderer || useFallback) - return false; - - if (!document()->securityOrigin()->canDisplay(url)) { - FrameLoader::reportLocalLoadFailed(m_frame, url.string()); - return false; - } - - FrameLoader* frameLoader = m_frame->loader(); - frameLoader->checkIfRunInsecureContent(document()->securityOrigin(), url); - - IntSize contentSize(renderer->contentWidth(), renderer->contentHeight()); - bool loadManually = document()->isPluginDocument() && !m_containsPlugins && toPluginDocument(document())->shouldLoadPluginManually(); - RefPtr<Widget> widget = frameLoader->client()->createPlugin(contentSize, - pluginElement, url, paramNames, paramValues, mimeType, loadManually); - - if (!widget) { - renderer->setShowsMissingPluginIndicator(); - return false; - } - - renderer->setWidget(widget); - m_containsPlugins = true; - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) || ENABLE(3D_PLUGIN) - pluginElement->setNeedsStyleRecalc(SyntheticStyleChange); -#endif - return true; -} - -KURL SubframeLoader::completeURL(const String& url) const -{ - ASSERT(m_frame->document()); - return m_frame->document()->completeURL(url); -} - -} // namespace WebCore diff --git a/WebCore/loader/SubframeLoader.h b/WebCore/loader/SubframeLoader.h deleted file mode 100644 index a573045..0000000 --- a/WebCore/loader/SubframeLoader.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (C) Research In Motion Limited 2009. 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 SubframeLoader_h -#define SubframeLoader_h - -#include "FrameLoaderTypes.h" -#include "PlatformString.h" -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class Document; -class Frame; -class FrameLoaderClient; -class HTMLAppletElement; -class HTMLFrameOwnerElement; -class HTMLPlugInImageElement; -class IntSize; -class KURL; -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) -class Node; -#endif -class Widget; - -// This is a slight misnomer. It handles the higher level logic of loading both subframes and plugins. -class SubframeLoader : public Noncopyable { -public: - SubframeLoader(Frame*); - - void clear(); - - bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName, bool lockHistory = true, bool lockBackForwardList = true); - bool requestObject(HTMLPlugInImageElement*, const String& url, const AtomicString& frameName, - const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); - -#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) - // FIXME: This should take Element* instead of Node*, or better yet the - // specific type of Element which this code depends on. - PassRefPtr<Widget> loadMediaPlayerProxyPlugin(Node*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues); -#endif - - PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args); - - bool allowPlugins(ReasonForCallingAllowPlugins); - - bool containsPlugins() const { return m_containsPlugins; } - - bool resourceWillUsePlugin(const String& url, const String& mimeType); - -private: - Frame* loadOrRedirectSubframe(HTMLFrameOwnerElement*, const KURL&, const AtomicString& frameName, bool lockHistory, bool lockBackForwardList); - Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); - bool loadPlugin(HTMLPlugInImageElement*, const KURL&, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); - - bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); - - Document* document() const; - - bool m_containsPlugins; - Frame* m_frame; - - KURL completeURL(const String&) const; -}; - -} // namespace WebCore - -#endif // SubframeLoader_h diff --git a/WebCore/loader/SubresourceLoader.cpp b/WebCore/loader/SubresourceLoader.cpp deleted file mode 100644 index 69f7906..0000000 --- a/WebCore/loader/SubresourceLoader.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2009 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 "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "ResourceHandle.h" -#include "SecurityOrigin.h" -#include "SubresourceLoaderClient.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 -} - -SubresourceLoader::~SubresourceLoader() -{ -#ifndef NDEBUG - subresourceLoaderCounter.decrement(); -#endif -} - -PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, SubresourceLoaderClient* client, const ResourceRequest& request, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks, bool shouldContentSniff) -{ - if (!frame) - return 0; - - FrameLoader* fl = frame->loader(); - if (securityCheck == DoSecurityCheck && (fl->state() == FrameStateProvisional || !fl->activeDocumentLoader() || fl->activeDocumentLoader()->isStopping())) - return 0; - - ResourceRequest newRequest = request; - - if (securityCheck == DoSecurityCheck && !frame->document()->securityOrigin()->canDisplay(request.url())) { - FrameLoader::reportLocalLoadFailed(frame, request.url().string()); - return 0; - } - - if (SecurityOrigin::shouldHideReferrer(request.url(), fl->outgoingReferrer())) - newRequest.clearHTTPReferrer(); - else if (!request.httpReferrer()) - newRequest.setHTTPReferrer(fl->outgoingReferrer()); - FrameLoader::addHTTPOriginIfNeeded(newRequest, fl->outgoingOrigin()); - - fl->addExtraFieldsToSubresourceRequest(newRequest); - - RefPtr<SubresourceLoader> subloader(adoptRef(new SubresourceLoader(frame, client, sendResourceLoadCallbacks, shouldContentSniff))); - subloader->documentLoader()->addSubresourceLoader(subloader.get()); - if (!subloader->init(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(0); - } -} - -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::didReceiveCachedMetadata(const char* data, int length) -{ - // 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->didReceiveCachedMetadata(this, data, length); -} - -void SubresourceLoader::didFinishLoading(double finishTime) -{ - 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(finishTime); -} - -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; - - // The only way the subresource loader can reach the terminal state here is if the run loop spins when calling - // m_client->didFail. This should in theory not happen which is why the assert is here. - ASSERT(!reachedTerminalState()); - if (reachedTerminalState()) - return; - - m_documentLoader->removeSubresourceLoader(this); - ResourceLoader::didCancel(error); -} - -bool SubresourceLoader::shouldUseCredentialStorage() -{ - RefPtr<SubresourceLoader> protect(this); - - bool shouldUse; - if (m_client && m_client->getShouldUseCredentialStorage(this, shouldUse)) - return shouldUse; - - return ResourceLoader::shouldUseCredentialStorage(); -} - -void SubresourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) -{ - RefPtr<SubresourceLoader> protect(this); - - ASSERT(handle()->hasAuthenticationChallenge()); - - 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; - - // It may have also handled authentication on its own. - if (!handle()->hasAuthenticationChallenge()) - 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 cb7ed81..0000000 --- a/WebCore/loader/SubresourceLoader.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2009 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 SubresourceLoader_h -#define SubresourceLoader_h - -#include "FrameLoaderTypes.h" -#include "ResourceLoader.h" - -namespace WebCore { - - class ResourceRequest; - class SubresourceLoaderClient; - - class SubresourceLoader : public ResourceLoader { - public: - static PassRefPtr<SubresourceLoader> create(Frame*, SubresourceLoaderClient*, const ResourceRequest&, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true, bool shouldContentSniff = true); - - void clearClient() { m_client = 0; } - - private: - SubresourceLoader(Frame*, SubresourceLoaderClient*, bool sendResourceLoadCallbacks, bool shouldContentSniff); - virtual ~SubresourceLoader(); - - 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 didReceiveCachedMetadata(const char*, int); - virtual void didFinishLoading(double finishTime); - virtual void didFail(const ResourceError&); - virtual bool shouldUseCredentialStorage(); - virtual void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); - virtual void receivedCancellation(const AuthenticationChallenge&); - 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 e18abe3..0000000 --- a/WebCore/loader/SubresourceLoaderClient.h +++ /dev/null @@ -1,62 +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 /*lengthReceived*/) { } - virtual void didReceiveCachedMetadata(SubresourceLoader*, const char*, int /*lengthReceived*/) { } - virtual void didFinishLoading(SubresourceLoader*) { } - virtual void didFail(SubresourceLoader*, const ResourceError&) { } - - virtual bool getShouldUseCredentialStorage(SubresourceLoader*, bool& /*shouldUseCredentialStorage*/) { return false; } - 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/TextResourceDecoder.cpp b/WebCore/loader/TextResourceDecoder.cpp deleted file mode 100644 index c8198e3..0000000 --- a/WebCore/loader/TextResourceDecoder.cpp +++ /dev/null @@ -1,694 +0,0 @@ -/* - Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "HTMLMetaCharsetParser.h" -#include "HTMLNames.h" -#include "TextCodec.h" -#include "TextEncoding.h" -#include "TextEncodingDetector.h" -#include "TextEncodingRegistry.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 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, bool usesEncodingDetector) - : m_contentType(determineContentType(mimeType)) - , m_encoding(defaultEncoding(m_contentType, specifiedDefaultEncoding)) - , m_source(DefaultEncoding) - , m_hintEncoding(0) - , m_checkedForBOM(false) - , m_checkedForCSSCharset(false) - , m_checkedForHeadCharset(false) - , m_useLenientXMLDecoding(false) - , m_sawError(false) - , m_usesEncodingDetector(usesEncodingDetector) -{ -} - -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_encoding = "windows-1252"; - else if (source == EncodingFromMetaTag || source == EncodingFromXMLHeader || source == EncodingFromCSSCharset) - m_encoding = encoding.closestByteBasedEquivalent(); - else - m_encoding = encoding; - - m_codec.clear(); - 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; -} - -size_t 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. - // We let it override even a user-chosen encoding. - ASSERT(!m_checkedForBOM); - - size_t lengthOfBOM = 0; - - size_t bufferLength = m_buffer.size(); - - size_t buf1Len = bufferLength; - size_t buf2Len = len; - const unsigned char* buf1 = reinterpret_cast<const unsigned char*>(m_buffer.data()); - const unsigned char* buf2 = reinterpret_cast<const unsigned char*>(data); - unsigned char c1 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; - unsigned char c2 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; - unsigned char c3 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0; - unsigned char c4 = buf2Len ? (--buf2Len, *buf2++) : 0; - - // Check for the BOM. - if (c1 == 0xFF && c2 == 0xFE) { - if (c3 != 0 || c4 != 0) { - setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding); - lengthOfBOM = 2; - } else { - setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding); - lengthOfBOM = 4; - } - } else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) { - setEncoding(UTF8Encoding(), AutoDetectedEncoding); - lengthOfBOM = 3; - } else if (c1 == 0xFE && c2 == 0xFF) { - setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding); - lengthOfBOM = 2; - } else if (c1 == 0 && c2 == 0 && c3 == 0xFE && c4 == 0xFF) { - setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding); - lengthOfBOM = 4; - } - - if (lengthOfBOM || bufferLength + len >= 4) - m_checkedForBOM = true; - - return lengthOfBOM; -} - -bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool& movedDataToBuffer) -{ - if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) { - 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; - - ++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; - if (p == pEnd) - return; - // Allow <!-->; other browsers do. - if (*p == '>') { - p++; - } else { - while (p + 2 < 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 + 3 < pEnd && p[1] == '-' && p[2] == '!' && p[3] == '>') { - p += 4; - break; - } - } - p++; - } - } - ptr = p; -} - -bool TextResourceDecoder::checkForHeadCharset(const char* data, size_t len, bool& movedDataToBuffer) -{ - if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) { - 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; - - // Continue with checking for an HTML meta tag if we were already doing so. - if (m_charsetParser) - return checkForMetaCharset(data, len); - - 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 = 0; - 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; - } - - // The HTTP-EQUIV meta has no effect on XHTML. - if (m_contentType == XML) - return true; - - m_charsetParser = HTMLMetaCharsetParser::create(); - return checkForMetaCharset(data, len); -} - -bool TextResourceDecoder::checkForMetaCharset(const char* data, size_t length) -{ - if (!m_charsetParser->checkForMetaCharset(data, length)) - return false; - - setEncoding(m_charsetParser->encoding(), EncodingFromMetaTag); - m_charsetParser.clear(); - m_checkedForHeadCharset = true; - return true; -} - -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; - } -} - -// We use the encoding detector in two cases: -// 1. Encoding detector is turned ON and no other encoding source is -// available (that is, it's DefaultEncoding). -// 2. Encoding detector is turned ON and the encoding is set to -// the encoding of the parent frame, which is also auto-detected. -// Note that condition #2 is NOT satisfied unless parent-child frame -// relationship is compliant to the same-origin policy. If they're from -// different domains, |m_source| would not be set to EncodingFromParentFrame -// in the first place. -bool TextResourceDecoder::shouldAutoDetect() const -{ - // Just checking m_hintEncoding suffices here because it's only set - // in setHintEncoding when the source is AutoDetectedEncoding. - return m_usesEncodingDetector - && (m_source == DefaultEncoding || (m_source == EncodingFromParentFrame && m_hintEncoding)); -} - -String TextResourceDecoder::decode(const char* data, size_t len) -{ - size_t lengthOfBOM = 0; - if (!m_checkedForBOM) - lengthOfBOM = 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 ""; - - // FIXME: It is wrong to change the encoding downstream after we have already done some decoding. - if (shouldAutoDetect()) { - if (m_encoding.isJapanese()) - detectJapaneseEncoding(data, len); // FIXME: We should use detectTextEncoding() for all languages. - else { - TextEncoding detectedEncoding; - if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding)) - setEncoding(detectedEncoding, AutoDetectedEncoding); - } - } - - ASSERT(m_encoding.isValid()); - - if (!m_codec) - m_codec = newTextCodec(m_encoding); - - if (m_buffer.isEmpty()) - return m_codec->decode(data + lengthOfBOM, len - lengthOfBOM, 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_codec->decode(m_buffer.data() + lengthOfBOM, m_buffer.size() - lengthOfBOM, false, m_contentType == XML && !m_useLenientXMLDecoding, m_sawError); - m_buffer.clear(); - return result; -} - -String TextResourceDecoder::flush() -{ - // If we can not identify the encoding even after a document is completely - // loaded, we need to detect the encoding if other conditions for - // autodetection is satisfied. - if (m_buffer.size() && shouldAutoDetect() - && ((!m_checkedForHeadCharset && (m_contentType == HTML || m_contentType == XML)) || (!m_checkedForCSSCharset && (m_contentType == CSS)))) { - TextEncoding detectedEncoding; - if (detectTextEncoding(m_buffer.data(), m_buffer.size(), - m_hintEncoding, &detectedEncoding)) - setEncoding(detectedEncoding, AutoDetectedEncoding); - } - - if (!m_codec) - m_codec = newTextCodec(m_encoding); - - String result = m_codec->decode(m_buffer.data(), m_buffer.size(), true, m_contentType == XML && !m_useLenientXMLDecoding, m_sawError); - m_buffer.clear(); - m_codec.clear(); - m_checkedForBOM = false; // Skip BOM again when re-decoding. - return result; -} - -} diff --git a/WebCore/loader/TextResourceDecoder.h b/WebCore/loader/TextResourceDecoder.h deleted file mode 100644 index 0bb855b..0000000 --- a/WebCore/loader/TextResourceDecoder.h +++ /dev/null @@ -1,101 +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 "TextEncoding.h" - -namespace WebCore { - -class HTMLMetaCharsetParser; - -class TextResourceDecoder : public RefCounted<TextResourceDecoder> { -public: - enum EncodingSource { - DefaultEncoding, - AutoDetectedEncoding, - EncodingFromXMLHeader, - EncodingFromMetaTag, - EncodingFromCSSCharset, - EncodingFromHTTPHeader, - UserChosenEncoding, - EncodingFromParentFrame - }; - - static PassRefPtr<TextResourceDecoder> create(const String& mimeType, const TextEncoding& defaultEncoding = TextEncoding(), bool usesEncodingDetector = false) - { - return adoptRef(new TextResourceDecoder(mimeType, defaultEncoding, usesEncodingDetector)); - } - ~TextResourceDecoder(); - - void setEncoding(const TextEncoding&, EncodingSource); - const TextEncoding& encoding() const { return m_encoding; } - - String decode(const char* data, size_t length); - String flush(); - - void setHintEncoding(const TextResourceDecoder* hintDecoder) - { - // hintEncoding is for use with autodetection, which should be - // only invoked when hintEncoding comes from auto-detection. - if (hintDecoder && hintDecoder->m_source == AutoDetectedEncoding) - m_hintEncoding = hintDecoder->encoding().name(); - } - - void useLenientXMLDecoding() { m_useLenientXMLDecoding = true; } - bool sawError() const { return m_sawError; } - -private: - TextResourceDecoder(const String& mimeType, const TextEncoding& defaultEncoding, - bool usesEncodingDetector); - - enum ContentType { PlainText, HTML, XML, CSS }; // PlainText only checks for BOM. - static ContentType determineContentType(const String& mimeType); - static const TextEncoding& defaultEncoding(ContentType, const TextEncoding& defaultEncoding); - - size_t checkForBOM(const char*, size_t); - bool checkForCSSCharset(const char*, size_t, bool& movedDataToBuffer); - bool checkForHeadCharset(const char*, size_t, bool& movedDataToBuffer); - bool checkForMetaCharset(const char*, size_t); - void detectJapaneseEncoding(const char*, size_t); - bool shouldAutoDetect() const; - - ContentType m_contentType; - TextEncoding m_encoding; - OwnPtr<TextCodec> m_codec; - EncodingSource m_source; - const char* m_hintEncoding; - Vector<char> m_buffer; - bool m_checkedForBOM; - bool m_checkedForCSSCharset; - bool m_checkedForHeadCharset; - bool m_useLenientXMLDecoding; // Don't stop on XML decoding errors. - bool m_sawError; - bool m_usesEncodingDetector; - - OwnPtr<HTMLMetaCharsetParser> m_charsetParser; -}; - -} - -#endif diff --git a/WebCore/loader/ThreadableLoader.cpp b/WebCore/loader/ThreadableLoader.cpp deleted file mode 100644 index 720ba4e..0000000 --- a/WebCore/loader/ThreadableLoader.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 "ThreadableLoader.h" - -#include "ScriptExecutionContext.h" -#include "Document.h" -#include "DocumentThreadableLoader.h" -#include "WorkerContext.h" -#include "WorkerRunLoop.h" -#include "WorkerThreadableLoader.h" - -namespace WebCore { - -PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options) -{ - ASSERT(client); - ASSERT(context); - -#if ENABLE(WORKERS) - if (context->isWorkerContext()) - return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, options); -#endif // ENABLE(WORKERS) - - ASSERT(context->isDocument()); - return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, options); -} - -void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) -{ - ASSERT(context); - -#if ENABLE(WORKERS) - if (context->isWorkerContext()) { - WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, options); - return; - } -#endif // ENABLE(WORKERS) - - ASSERT(context->isDocument()); - DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, options); -} - -} // namespace WebCore diff --git a/WebCore/loader/ThreadableLoader.h b/WebCore/loader/ThreadableLoader.h deleted file mode 100644 index f41a774..0000000 --- a/WebCore/loader/ThreadableLoader.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 ThreadableLoader_h -#define ThreadableLoader_h - -#include <wtf/Noncopyable.h> -#include <wtf/PassRefPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - - class ResourceError; - class ResourceRequest; - class ResourceResponse; - class ScriptExecutionContext; - class ThreadableLoaderClient; - - enum StoredCredentials { - AllowStoredCredentials, - DoNotAllowStoredCredentials - }; - - enum CrossOriginRequestPolicy { - DenyCrossOriginRequests, - UseAccessControl, - AllowCrossOriginRequests - }; - - struct ThreadableLoaderOptions { - ThreadableLoaderOptions() : sendLoadCallbacks(false), sniffContent(false), allowCredentials(false), forcePreflight(false), crossOriginRequestPolicy(DenyCrossOriginRequests) { } - bool sendLoadCallbacks; - bool sniffContent; - bool allowCredentials; // Whether HTTP credentials and cookies are sent with the request. - bool forcePreflight; // If AccessControl is used, whether to force a preflight. - CrossOriginRequestPolicy crossOriginRequestPolicy; - }; - - // Useful for doing loader operations from any thread (not threadsafe, - // just able to run on threads other than the main thread). - class ThreadableLoader : public Noncopyable { - public: - static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&); - static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&); - - virtual void cancel() = 0; - void ref() { refThreadableLoader(); } - void deref() { derefThreadableLoader(); } - - protected: - virtual ~ThreadableLoader() { } - virtual void refThreadableLoader() = 0; - virtual void derefThreadableLoader() = 0; - }; - -} // namespace WebCore - -#endif // ThreadableLoader_h diff --git a/WebCore/loader/ThreadableLoaderClient.h b/WebCore/loader/ThreadableLoaderClient.h deleted file mode 100644 index bcf68be..0000000 --- a/WebCore/loader/ThreadableLoaderClient.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 ThreadableLoaderClient_h -#define ThreadableLoaderClient_h - -#include <wtf/Noncopyable.h> - -namespace WebCore { - - class ResourceError; - class ResourceResponse; - - class ThreadableLoaderClient : public Noncopyable { - public: - virtual void didSendData(unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/) { } - - virtual void didReceiveResponse(const ResourceResponse&) { } - virtual void didReceiveData(const char*, int /*lengthReceived*/) { } - virtual void didFinishLoading(unsigned long /*identifier*/) { } - virtual void didFail(const ResourceError&) { } - virtual void didFailRedirectCheck() { } - - virtual void didReceiveAuthenticationCancellation(const ResourceResponse&) { } - - protected: - virtual ~ThreadableLoaderClient() { } - }; - -} // namespace WebCore - -#endif // ThreadableLoaderClient_h diff --git a/WebCore/loader/ThreadableLoaderClientWrapper.h b/WebCore/loader/ThreadableLoaderClientWrapper.h deleted file mode 100644 index d3c1a9f..0000000 --- a/WebCore/loader/ThreadableLoaderClientWrapper.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 ThreadableLoaderClientWrapper_h -#define ThreadableLoaderClientWrapper_h - -#include "ThreadableLoaderClient.h" -#include <wtf/Noncopyable.h> -#include <wtf/PassRefPtr.h> -#include <wtf/Threading.h> - -namespace WebCore { - - class ThreadableLoaderClientWrapper : public ThreadSafeShared<ThreadableLoaderClientWrapper> { - public: - static PassRefPtr<ThreadableLoaderClientWrapper> create(ThreadableLoaderClient* client) - { - return adoptRef(new ThreadableLoaderClientWrapper(client)); - } - - void clearClient() - { - m_done = true; - m_client = 0; - } - - bool done() const - { - return m_done; - } - - void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) - { - if (m_client) - m_client->didSendData(bytesSent, totalBytesToBeSent); - } - - void didReceiveResponse(const ResourceResponse& response) - { - if (m_client) - m_client->didReceiveResponse(response); - } - - void didReceiveData(const char* data, int lengthReceived) - { - if (m_client) - m_client->didReceiveData(data, lengthReceived); - } - - void didFinishLoading(unsigned long identifier) - { - m_done = true; - if (m_client) - m_client->didFinishLoading(identifier); - } - - void didFail(const ResourceError& error) - { - m_done = true; - if (m_client) - m_client->didFail(error); - } - - void didFailRedirectCheck() - { - m_done = true; - if (m_client) - m_client->didFailRedirectCheck(); - } - - void didReceiveAuthenticationCancellation(const ResourceResponse& response) - { - if (m_client) - m_client->didReceiveResponse(response); - } - - protected: - ThreadableLoaderClientWrapper(ThreadableLoaderClient* client) - : m_client(client) - , m_done(false) - { - } - - ThreadableLoaderClient* m_client; - bool m_done; - }; - -} // namespace WebCore - -#endif // ThreadableLoaderClientWrapper_h diff --git a/WebCore/loader/WorkerThreadableLoader.cpp b/WebCore/loader/WorkerThreadableLoader.cpp deleted file mode 100644 index 4d18c28..0000000 --- a/WebCore/loader/WorkerThreadableLoader.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2009, 2010 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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(WORKERS) - -#include "WorkerThreadableLoader.h" - -#include "CrossThreadTask.h" -#include "ResourceError.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "ThreadableLoader.h" -#include "WorkerContext.h" -#include "WorkerLoaderProxy.h" -#include "WorkerThread.h" -#include <wtf/OwnPtr.h> -#include <wtf/Threading.h> -#include <wtf/Vector.h> - -using namespace std; - -namespace WebCore { - -static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode"; - -WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options) - : m_workerContext(workerContext) - , m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client)) - , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, options))) -{ -} - -WorkerThreadableLoader::~WorkerThreadableLoader() -{ - m_bridge.destroy(); -} - -void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options) -{ - WorkerRunLoop& runLoop = workerContext->thread()->runLoop(); - - // Create a unique mode just for this synchronous resource load. - String mode = loadResourceSynchronouslyMode; - mode.append(String::number(runLoop.createUniqueId())); - - RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, options); - MessageQueueWaitResult result = MessageQueueMessageReceived; - while (!loader->done() && result != MessageQueueTerminated) - result = runLoop.runInMode(workerContext, mode); - - if (!loader->done() && result == MessageQueueTerminated) - loader->cancel(); -} - -void WorkerThreadableLoader::cancel() -{ - m_bridge.cancel(); -} - -WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode, - const ResourceRequest& request, const ThreadableLoaderOptions& options) - : m_workerClientWrapper(workerClientWrapper) - , m_loaderProxy(loaderProxy) - , m_taskMode(taskMode.crossThreadString()) -{ - ASSERT(m_workerClientWrapper.get()); - m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, options)); -} - -WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge() -{ -} - -void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, PassOwnPtr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options) -{ - ASSERT(isMainThread()); - ASSERT(context->isDocument()); - - // FIXME: the created loader has no knowledge of the origin of the worker doing the load request. - // Basically every setting done in SubresourceLoader::create (including the contents of addExtraFieldsToRequest) - // needs to be examined for how it should take into account a different originator. - OwnPtr<ResourceRequest> request(ResourceRequest::adopt(requestData)); - // FIXME: If the a site requests a local resource, then this will return a non-zero value but the sync path - // will return a 0 value. Either this should return 0 or the other code path should do a callback with - // a failure. - thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, options); - ASSERT(thisPtr->m_mainThreadLoader); -} - -void WorkerThreadableLoader::MainThreadBridge::mainThreadDestroy(ScriptExecutionContext* context, MainThreadBridge* thisPtr) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - delete thisPtr; -} - -void WorkerThreadableLoader::MainThreadBridge::destroy() -{ - // Ensure that no more client callbacks are done in the worker context's thread. - clearClientWrapper(); - - // "delete this" and m_mainThreadLoader::deref() on the worker object's thread. - m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadDestroy, this)); -} - -void WorkerThreadableLoader::MainThreadBridge::mainThreadCancel(ScriptExecutionContext* context, MainThreadBridge* thisPtr) -{ - ASSERT(isMainThread()); - ASSERT_UNUSED(context, context->isDocument()); - - if (!thisPtr->m_mainThreadLoader) - return; - thisPtr->m_mainThreadLoader->cancel(); - thisPtr->m_mainThreadLoader = 0; -} - -void WorkerThreadableLoader::MainThreadBridge::cancel() -{ - m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCancel, this)); - ThreadableLoaderClientWrapper* clientWrapper = m_workerClientWrapper.get(); - if (!clientWrapper->done()) { - // If the client hasn't reached a termination state, then transition it by sending a cancellation error. - // Note: no more client callbacks will be done after this method -- the clearClientWrapper() call ensures that. - ResourceError error(String(), 0, String(), String()); - error.setIsCancellation(true); - clientWrapper->didFail(error); - } - clearClientWrapper(); -} - -void WorkerThreadableLoader::MainThreadBridge::clearClientWrapper() -{ - m_workerClientWrapper->clearClient(); -} - -static void workerContextDidSendData(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - workerClientWrapper->didSendData(bytesSent, totalBytesToBeSent); -} - -void WorkerThreadableLoader::MainThreadBridge::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidSendData, m_workerClientWrapper, bytesSent, totalBytesToBeSent), m_taskMode); -} - -static void workerContextDidReceiveResponse(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, PassOwnPtr<CrossThreadResourceResponseData> responseData) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - OwnPtr<ResourceResponse> response(ResourceResponse::adopt(responseData)); - workerClientWrapper->didReceiveResponse(*response); -} - -void WorkerThreadableLoader::MainThreadBridge::didReceiveResponse(const ResourceResponse& response) -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveResponse, m_workerClientWrapper, response), m_taskMode); -} - -static void workerContextDidReceiveData(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, PassOwnPtr<Vector<char> > vectorData) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - workerClientWrapper->didReceiveData(vectorData->data(), vectorData->size()); -} - -void WorkerThreadableLoader::MainThreadBridge::didReceiveData(const char* data, int lengthReceived) -{ - OwnPtr<Vector<char> > vector = adoptPtr(new Vector<char>(lengthReceived)); // needs to be an OwnPtr for usage with createCallbackTask. - memcpy(vector->data(), data, lengthReceived); - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveData, m_workerClientWrapper, vector.release()), m_taskMode); -} - -static void workerContextDidFinishLoading(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, unsigned long identifier) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - workerClientWrapper->didFinishLoading(identifier); -} - -void WorkerThreadableLoader::MainThreadBridge::didFinishLoading(unsigned long identifier) -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFinishLoading, m_workerClientWrapper, identifier), m_taskMode); -} - -static void workerContextDidFail(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, const ResourceError& error) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - workerClientWrapper->didFail(error); -} - -void WorkerThreadableLoader::MainThreadBridge::didFail(const ResourceError& error) -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFail, m_workerClientWrapper, error), m_taskMode); -} - -static void workerContextDidFailRedirectCheck(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - workerClientWrapper->didFailRedirectCheck(); -} - -void WorkerThreadableLoader::MainThreadBridge::didFailRedirectCheck() -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidFailRedirectCheck, m_workerClientWrapper), m_taskMode); -} - -static void workerContextDidReceiveAuthenticationCancellation(ScriptExecutionContext* context, RefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, PassOwnPtr<CrossThreadResourceResponseData> responseData) -{ - ASSERT_UNUSED(context, context->isWorkerContext()); - OwnPtr<ResourceResponse> response(ResourceResponse::adopt(responseData)); - workerClientWrapper->didReceiveAuthenticationCancellation(*response); -} - -void WorkerThreadableLoader::MainThreadBridge::didReceiveAuthenticationCancellation(const ResourceResponse& response) -{ - m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidReceiveAuthenticationCancellation, m_workerClientWrapper, response), m_taskMode); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/loader/WorkerThreadableLoader.h b/WebCore/loader/WorkerThreadableLoader.h deleted file mode 100644 index 81da2e0..0000000 --- a/WebCore/loader/WorkerThreadableLoader.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2009 Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 WorkerThreadableLoader_h -#define WorkerThreadableLoader_h - -#if ENABLE(WORKERS) - -#include "PlatformString.h" -#include "ThreadableLoader.h" -#include "ThreadableLoaderClient.h" -#include "ThreadableLoaderClientWrapper.h" - -#include <wtf/PassOwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/Threading.h> - -namespace WebCore { - - class ResourceError; - class ResourceRequest; - class WorkerContext; - class WorkerLoaderProxy; - struct CrossThreadResourceResponseData; - struct CrossThreadResourceRequestData; - - class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader { - public: - static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&); - static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options) - { - return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, options)); - } - - ~WorkerThreadableLoader(); - - virtual void cancel(); - - bool done() const { return m_workerClientWrapper->done(); } - - using RefCounted<WorkerThreadableLoader>::ref; - using RefCounted<WorkerThreadableLoader>::deref; - - protected: - virtual void refThreadableLoader() { ref(); } - virtual void derefThreadableLoader() { deref(); } - - private: - // Creates a loader on the main thread and bridges communication between - // the main thread and the worker context's thread where WorkerThreadableLoader runs. - // - // Regarding the bridge and lifetimes of items used in callbacks, there are a few cases: - // - // all cases. All tasks posted from the worker context's thread are ok because - // the last task posted always is "mainThreadDestroy", so MainThreadBridge is - // around for all tasks that use it on the main thread. - // - // case 1. worker.terminate is called. - // In this case, no more tasks are posted from the worker object's thread to the worker - // context's thread -- WorkerContextProxy implementation enforces this. - // - // case 2. xhr gets aborted and the worker context continues running. - // The ThreadableLoaderClientWrapper has the underlying client cleared, so no more calls - // go through it. All tasks posted from the worker object's thread to the worker context's - // thread do "ThreadableLoaderClientWrapper::ref" (automatically inside of the cross thread copy - // done in createCallbackTask), so the ThreadableLoaderClientWrapper instance is there until all - // tasks are executed. - class MainThreadBridge : public ThreadableLoaderClient { - public: - // All executed on the worker context's thread. - MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&); - void cancel(); - void destroy(); - - private: - // Executed on the worker context's thread. - void clearClientWrapper(); - - // All executed on the main thread. - static void mainThreadDestroy(ScriptExecutionContext*, MainThreadBridge*); - ~MainThreadBridge(); - - static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, PassOwnPtr<CrossThreadResourceRequestData>, ThreadableLoaderOptions); - static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*); - virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); - virtual void didReceiveResponse(const ResourceResponse&); - virtual void didReceiveData(const char*, int lengthReceived); - virtual void didFinishLoading(unsigned long identifier); - virtual void didFail(const ResourceError&); - virtual void didFailRedirectCheck(); - virtual void didReceiveAuthenticationCancellation(const ResourceResponse&); - - // Only to be used on the main thread. - RefPtr<ThreadableLoader> m_mainThreadLoader; - - // ThreadableLoaderClientWrapper is to be used on the worker context thread. - // The ref counting is done on either thread. - RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper; - - // May be used on either thread. - WorkerLoaderProxy& m_loaderProxy; - - // For use on the main thread. - String m_taskMode; - }; - - WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&); - - RefPtr<WorkerContext> m_workerContext; - RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper; - MainThreadBridge& m_bridge; - }; - -} // namespace WebCore - -#endif // ENABLE(WORKERS) - -#endif // WorkerThreadableLoader_h diff --git a/WebCore/loader/appcache/ApplicationCache.cpp b/WebCore/loader/appcache/ApplicationCache.cpp deleted file mode 100644 index 2a93765..0000000 --- a/WebCore/loader/appcache/ApplicationCache.cpp +++ /dev/null @@ -1,204 +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 <wtf/text/CString.h> -#include <stdio.h> - -namespace WebCore { - -ApplicationCache::ApplicationCache() - : m_group(0) - , m_manifest(0) - , m_estimatedSizeInStorage(0) - , m_storageID(0) -{ -} - -ApplicationCache::~ApplicationCache() -{ - if (m_group && !m_group->isCopy()) - m_group->cacheDestroyed(this); -} - -void ApplicationCache::setGroup(ApplicationCacheGroup* group) -{ - ASSERT(!m_group || group == m_group); - m_group = group; -} - -bool ApplicationCache::isComplete() const -{ - return !m_group->cacheIsBeingUpdated(this); -} - -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()); - ASSERT(resource->type() & ApplicationCacheResource::Master); - - // Add the resource to the storage. - cacheStorage().store(resource.get(), this); - } - - m_estimatedSizeInStorage += resource->estimatedSizeInStorage(); - - 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); - - m_estimatedSizeInStorage -= it->second->estimatedSizeInStorage(); - - return type; -} - -ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url) -{ - ASSERT(!KURL(ParsedURLString, url).hasFragmentIdentifier()); - return m_resources.get(url).get(); -} - -bool ApplicationCache::requestIsHTTPOrHTTPSGet(const ResourceRequest& request) -{ - if (!request.url().protocolInHTTPFamily()) - 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 0; - - KURL url(request.url()); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - return resourceForURL(url); -} - -void ApplicationCache::setOnlineWhitelist(const Vector<KURL>& onlineWhitelist) -{ - ASSERT(m_onlineWhitelist.isEmpty()); - m_onlineWhitelist = onlineWhitelist; -} - -bool ApplicationCache::isURLInOnlineWhitelist(const KURL& url) -{ - if (m_allowAllNetworkRequests) - return true; - - size_t whitelistSize = m_onlineWhitelist.size(); - for (size_t i = 0; i < whitelistSize; ++i) { - if (protocolHostAndPortAreEqual(url, m_onlineWhitelist[i]) && url.string().startsWith(m_onlineWhitelist[i].string())) - return true; - } - return false; -} - -void ApplicationCache::setFallbackURLs(const FallbackURLVector& fallbackURLs) -{ - ASSERT(m_fallbackURLs.isEmpty()); - m_fallbackURLs = fallbackURLs; -} - -bool ApplicationCache::urlMatchesFallbackNamespace(const KURL& url, KURL* fallbackURL) -{ - size_t fallbackCount = m_fallbackURLs.size(); - for (size_t i = 0; i < fallbackCount; ++i) { - if (protocolHostAndPortAreEqual(url, m_fallbackURLs[i].first) && url.string().startsWith(m_fallbackURLs[i].first.string())) { - if (fallbackURL) - *fallbackURL = m_fallbackURLs[i].second; - return true; - } - } - return false; -} - -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 f073499..0000000 --- a/WebCore/loader/appcache/ApplicationCache.h +++ /dev/null @@ -1,116 +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 "PlatformString.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class ApplicationCacheGroup; -class ApplicationCacheResource; -class DocumentLoader; -class KURL; -class ResourceRequest; - -typedef Vector<std::pair<KURL, KURL> > FallbackURLVector; - -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; } - - bool isComplete() const; - - ApplicationCacheResource* resourceForRequest(const ResourceRequest&); - ApplicationCacheResource* resourceForURL(const String& url); - - void setAllowsAllNetworkRequests(bool value) { m_allowAllNetworkRequests = value; } - bool allowsAllNetworkRequests() const { return m_allowAllNetworkRequests; } - void setOnlineWhitelist(const Vector<KURL>& onlineWhitelist); - const Vector<KURL>& onlineWhitelist() const { return m_onlineWhitelist; } - bool isURLInOnlineWhitelist(const KURL&); // There is an entry in online whitelist that has the same origin as the resource's URL and that is a prefix match for the resource's URL. - - void setFallbackURLs(const FallbackURLVector&); - const FallbackURLVector& fallbackURLs() const { return m_fallbackURLs; } - bool urlMatchesFallbackNamespace(const KURL&, KURL* fallbackURL = 0); - -#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&); - - int64_t estimatedSizeInStorage() const { return m_estimatedSizeInStorage; } - -private: - ApplicationCache(); - - ApplicationCacheGroup* m_group; - ResourceMap m_resources; - ApplicationCacheResource* m_manifest; - - bool m_allowAllNetworkRequests; - Vector<KURL> m_onlineWhitelist; - FallbackURLVector m_fallbackURLs; - - // The total size of the resources belonging to this Application Cache instance. - // This is an estimation of the size this Application Cache occupies in the - // database file. - int64_t m_estimatedSizeInStorage; - - 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 6454b90..0000000 --- a/WebCore/loader/appcache/ApplicationCacheGroup.cpp +++ /dev/null @@ -1,1181 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 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 "ApplicationCacheHost.h" -#include "ApplicationCacheResource.h" -#include "ApplicationCacheStorage.h" -#include "Chrome.h" -#include "ChromeClient.h" -#include "DocumentLoader.h" -#include "DOMApplicationCache.h" -#include "DOMWindow.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "MainResourceLoader.h" -#include "ManifestParser.h" -#include "Page.h" -#include "SecurityOrigin.h" -#include "Settings.h" -#include <wtf/HashMap.h> - -#if ENABLE(INSPECTOR) -#include "InspectorApplicationCacheAgent.h" -#include "InspectorController.h" -#include "ProgressTracker.h" -#else -#include <wtf/UnusedParam.h> -#endif - -namespace WebCore { - -ApplicationCacheGroup::ApplicationCacheGroup(const KURL& manifestURL, bool isCopy) - : m_manifestURL(manifestURL) - , m_origin(SecurityOrigin::create(manifestURL)) - , m_updateStatus(Idle) - , m_downloadingPendingMasterResourceLoadersCount(0) - , m_progressTotal(0) - , m_progressDone(0) - , m_frame(0) - , m_storageID(0) - , m_isObsolete(false) - , m_completionType(None) - , m_isCopy(isCopy) - , m_calledReachedMaxAppCacheSize(false) - , m_loadedSize(0) - , m_availableSpaceInQuota(ApplicationCacheStorage::unknownQuota()) - , m_originQuotaReached(false) -{ -} - -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_pendingMasterResourceLoaders.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*) -{ - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) - return 0; - - KURL url(request.url()); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(url)) { - ASSERT(group->newestCache()); - ASSERT(!group->isObsolete()); - - return group->newestCache(); - } - - return 0; -} - -ApplicationCache* ApplicationCacheGroup::fallbackCacheForMainRequest(const ResourceRequest& request, DocumentLoader*) -{ - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) - return 0; - - KURL url(request.url()); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - if (ApplicationCacheGroup* group = cacheStorage().fallbackCacheGroupForURL(url)) { - ASSERT(group->newestCache()); - ASSERT(!group->isObsolete()); - - return group->newestCache(); - } - - return 0; -} - -void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& passedManifestURL) -{ - ASSERT(frame && frame->page()); - - if (!frame->settings()->offlineWebApplicationCacheEnabled()) - return; - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - ASSERT(!documentLoader->applicationCacheHost()->applicationCache()); - - if (passedManifestURL.isNull()) { - selectCacheWithoutManifestURL(frame); - return; - } - - KURL manifestURL(passedManifestURL); - if (manifestURL.hasFragmentIdentifier()) - manifestURL.removeFragmentIdentifier(); - - ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache(); - - if (mainResourceCache) { - if (manifestURL == mainResourceCache->group()->m_manifestURL) { - // The cache may have gotten obsoleted after we've loaded from it, but before we parsed the document and saw cache manifest. - if (mainResourceCache->group()->isObsolete()) - return; - mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache); - mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext); - } else { - // The main resource was loaded from cache, so the cache must have an entry for it. Mark it as foreign. - KURL resourceURL(documentLoader->responseURL()); - if (resourceURL.hasFragmentIdentifier()) - resourceURL.removeFragmentIdentifier(); - ApplicationCacheResource* resource = mainResourceCache->resourceForURL(resourceURL); - bool inStorage = resource->storageID(); - resource->addType(ApplicationCacheResource::Foreign); - if (inStorage) - cacheStorage().storeUpdatedType(resource, mainResourceCache); - - // Restart the current navigation from the top of the navigation algorithm, undoing any changes that were made - // as part of the initial load. - // The navigation will not result in the same resource being loaded, because "foreign" entries are never picked during navigation. - frame->navigationScheduler()->scheduleLocationChange(frame->document()->securityOrigin(), documentLoader->url(), frame->loader()->referrer(), true); - } - - 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)) - return; - - // Check that the resource URL has the same scheme/host/port as the manifest URL. - if (!protocolHostAndPortAreEqual(manifestURL, request.url())) - return; - - // Don't change anything on disk if private browsing is enabled. - if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) { - postListenerTask(ApplicationCacheHost::CHECKING_EVENT, documentLoader); - postListenerTask(ApplicationCacheHost::ERROR_EVENT, documentLoader); - return; - } - - ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL); - - documentLoader->applicationCacheHost()->setCandidateApplicationCacheGroup(group); - group->m_pendingMasterResourceLoaders.add(documentLoader); - group->m_downloadingPendingMasterResourceLoadersCount++; - - ASSERT(!group->m_cacheBeingUpdated || group->m_updateStatus != Idle); - group->update(frame, ApplicationCacheUpdateWithBrowsingContext); -} - -void ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame* frame) -{ - if (!frame->settings()->offlineWebApplicationCacheEnabled()) - return; - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - ASSERT(!documentLoader->applicationCacheHost()->applicationCache()); - - ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache(); - - if (mainResourceCache) { - mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache); - mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext); - } -} - -void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader) -{ - ASSERT(m_pendingMasterResourceLoaders.contains(loader)); - ASSERT(m_completionType == None || m_pendingEntries.isEmpty()); - KURL url = loader->url(); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - switch (m_completionType) { - case None: - // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later. - return; - case NoUpdate: - ASSERT(!m_cacheBeingUpdated); - associateDocumentLoaderWithCache(loader, m_newestCache.get()); - - if (ApplicationCacheResource* resource = m_newestCache->resourceForURL(url)) { - if (!(resource->type() & ApplicationCacheResource::Master)) { - resource->addType(ApplicationCacheResource::Master); - ASSERT(!resource->storageID()); - } - } else - m_newestCache->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData())); - - break; - case Failure: - // Cache update has been a failure, so there is no reason to keep the document associated with the incomplete cache - // (its main resource was not cached yet, so it is likely that the application changed significantly server-side). - ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading(). - loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too. - m_associatedDocumentLoaders.remove(loader); - postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); - break; - case Completed: - ASSERT(m_associatedDocumentLoaders.contains(loader)); - - if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) { - if (!(resource->type() & ApplicationCacheResource::Master)) { - resource->addType(ApplicationCacheResource::Master); - ASSERT(!resource->storageID()); - } - } else - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData())); - // The "cached" event will be posted to all associated documents once update is complete. - break; - } - - m_downloadingPendingMasterResourceLoadersCount--; - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader* loader) -{ - ASSERT(m_pendingMasterResourceLoaders.contains(loader)); - ASSERT(m_completionType == None || m_pendingEntries.isEmpty()); - - switch (m_completionType) { - case None: - // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later. - return; - case NoUpdate: - ASSERT(!m_cacheBeingUpdated); - - // The manifest didn't change, and we have a relevant cache - but the main resource download failed mid-way, so it cannot be stored to the cache, - // and the loader does not get associated to it. If there are other main resources being downloaded for this cache group, they may still succeed. - postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); - - break; - case Failure: - // Cache update failed, too. - ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading(). - ASSERT(!loader->applicationCacheHost()->applicationCache() || loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated); - - loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too. - m_associatedDocumentLoaders.remove(loader); - postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); - break; - case Completed: - // The cache manifest didn't list this main resource, and all cache entries were already updated successfully - but the main resource failed to load, - // so it cannot be stored to the cache. If there are other main resources being downloaded for this cache group, they may still succeed. - ASSERT(m_associatedDocumentLoaders.contains(loader)); - ASSERT(loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated); - ASSERT(!loader->applicationCacheHost()->candidateApplicationCacheGroup()); - m_associatedDocumentLoaders.remove(loader); - loader->applicationCacheHost()->setApplicationCache(0); - - postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); - - break; - } - - m_downloadingPendingMasterResourceLoadersCount--; - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::stopLoading() -{ - if (m_manifestHandle) { - ASSERT(!m_currentHandle); - - 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; - m_pendingEntries.clear(); -} - -void ApplicationCacheGroup::disassociateDocumentLoader(DocumentLoader* loader) -{ - HashSet<DocumentLoader*>::iterator it = m_associatedDocumentLoaders.find(loader); - if (it != m_associatedDocumentLoaders.end()) - m_associatedDocumentLoaders.remove(it); - - m_pendingMasterResourceLoaders.remove(loader); - - loader->applicationCacheHost()->setApplicationCache(0); // Will set candidate to 0, too. - - if (!m_associatedDocumentLoaders.isEmpty() || !m_pendingMasterResourceLoaders.isEmpty()) - return; - - if (m_caches.isEmpty()) { - // There is an initial cache attempt in progress. - ASSERT(!m_newestCache); - // Delete ourselves, causing the cache attempt to be stopped. - delete this; - return; - } - - ASSERT(m_caches.contains(m_newestCache.get())); - - // Release our reference to the newest cache. This could cause us to be deleted. - // Any ongoing updates will be stopped from destructor. - m_newestCache.release(); -} - -void ApplicationCacheGroup::cacheDestroyed(ApplicationCache* cache) -{ - if (!m_caches.contains(cache)) - return; - - m_caches.remove(cache); - - if (m_caches.isEmpty()) { - ASSERT(m_associatedDocumentLoaders.isEmpty()); - ASSERT(m_pendingMasterResourceLoaders.isEmpty()); - delete this; - } -} - -void ApplicationCacheGroup::stopLoadingInFrame(Frame* frame) -{ - if (frame != m_frame) - return; - - stopLoading(); -} - -#if ENABLE(INSPECTOR) -static void inspectorUpdateApplicationCacheStatus(Frame* frame) -{ - if (!frame) - return; - - if (Page *page = frame->page()) { - if (InspectorApplicationCacheAgent* applicationCacheAgent = page->inspectorController()->applicationCacheAgent()) { - ApplicationCacheHost::Status status = frame->loader()->documentLoader()->applicationCacheHost()->status(); - applicationCacheAgent->updateApplicationCacheStatus(status); - } - } -} -#endif - -void ApplicationCacheGroup::setNewestCache(PassRefPtr<ApplicationCache> newestCache) -{ - m_newestCache = newestCache; - - m_caches.add(m_newestCache.get()); - m_newestCache->setGroup(this); -#if ENABLE(INSPECTOR) - inspectorUpdateApplicationCacheStatus(m_frame); -#endif -} - -void ApplicationCacheGroup::makeObsolete() -{ - if (isObsolete()) - return; - - m_isObsolete = true; - cacheStorage().cacheGroupMadeObsolete(this); - ASSERT(!m_storageID); -#if ENABLE(INSPECTOR) - inspectorUpdateApplicationCacheStatus(m_frame); -#endif -} - -void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption updateOption) -{ - if (m_updateStatus == Checking || m_updateStatus == Downloading) { - if (updateOption == ApplicationCacheUpdateWithBrowsingContext) { - postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader()); - if (m_updateStatus == Downloading) - postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, frame->loader()->documentLoader()); - } - return; - } - - // Don't change anything on disk if private browsing is enabled. - if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) { - ASSERT(m_pendingMasterResourceLoaders.isEmpty()); - ASSERT(m_pendingEntries.isEmpty()); - ASSERT(!m_cacheBeingUpdated); - postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader()); - postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, frame->loader()->documentLoader()); - return; - } - - ASSERT(!m_frame); - m_frame = frame; - - setUpdateStatus(Checking); - - postListenerTask(ApplicationCacheHost::CHECKING_EVENT, m_associatedDocumentLoaders); - if (!m_newestCache) { - ASSERT(updateOption == ApplicationCacheUpdateWithBrowsingContext); - postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader()); - } - - ASSERT(!m_manifestHandle); - ASSERT(!m_manifestResource); - ASSERT(m_completionType == None); - - // FIXME: Handle defer loading - m_manifestHandle = createResourceHandle(m_manifestURL, m_newestCache ? m_newestCache->manifestResource() : 0); -} - -PassRefPtr<ResourceHandle> ApplicationCacheGroup::createResourceHandle(const KURL& url, ApplicationCacheResource* newestCachedResource) -{ - ResourceRequest request(url); - m_frame->loader()->applyUserAgent(request); - request.setHTTPHeaderField("Cache-Control", "max-age=0"); - - if (newestCachedResource) { - const String& lastModified = newestCachedResource->response().httpHeaderField("Last-Modified"); - const String& eTag = newestCachedResource->response().httpHeaderField("ETag"); - if (!lastModified.isEmpty() || !eTag.isEmpty()) { - if (!lastModified.isEmpty()) - request.setHTTPHeaderField("If-Modified-Since", lastModified); - if (!eTag.isEmpty()) - request.setHTTPHeaderField("If-None-Match", eTag); - } - } - - RefPtr<ResourceHandle> handle = ResourceHandle::create(m_frame->loader()->networkingContext(), request, this, false, true); -#if ENABLE(INSPECTOR) - // Because willSendRequest only gets called during redirects, we initialize - // the identifier and the first willSendRequest here. - m_currentResourceIdentifier = m_frame->page()->progress()->createUniqueIdentifier(); - if (Page* page = m_frame->page()) { - InspectorController* inspectorController = page->inspectorController(); - inspectorController->identifierForInitialRequest(m_currentResourceIdentifier, m_frame->loader()->documentLoader(), handle->firstRequest()); - ResourceResponse redirectResponse = ResourceResponse(); - inspectorController->willSendRequest(m_currentResourceIdentifier, request, redirectResponse); - } -#endif - return handle; -} - -#if ENABLE(INSPECTOR) -void ApplicationCacheGroup::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - // This only gets called by ResourceHandleMac if there is a redirect. - if (Page* page = m_frame->page()) - page->inspectorController()->willSendRequest(m_currentResourceIdentifier, request, redirectResponse); -} -#endif - -void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response) -{ -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) { - if (handle == m_manifestHandle) { - if (InspectorApplicationCacheAgent* applicationCacheAgent = page->inspectorController()->applicationCacheAgent()) - applicationCacheAgent->didReceiveManifestResponse(m_currentResourceIdentifier, response); - } else - page->inspectorController()->didReceiveResponse(m_currentResourceIdentifier, m_frame->loader()->documentLoader(), response); - } -#endif - - if (handle == m_manifestHandle) { - didReceiveManifestResponse(response); - return; - } - - ASSERT(handle == m_currentHandle); - - KURL url(handle->firstRequest().url()); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - 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 master resources delivered here. - if (!m_newestCache) - ASSERT(!(type & ApplicationCacheResource::Master)); - - if (m_newestCache && response.httpStatusCode() == 304) { // Not modified. - ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url); - if (newestCachedResource) { - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); - m_pendingEntries.remove(m_currentHandle->firstRequest().url()); - m_currentHandle->cancel(); - m_currentHandle = 0; - // Load the next resource, if any. - startLoadingEntry(); - return; - } - // The server could return 304 for an unconditional request - in this case, we handle the response as a normal error. - } - - if (response.httpStatusCode() / 100 != 2 || response.url() != m_currentHandle->firstRequest().url()) { - if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) { - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); - } else if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) { - // Skip this resource. It is dropped from the cache. - m_currentHandle->cancel(); - m_currentHandle = 0; - m_pendingEntries.remove(url); - // Load the next resource, if any. - startLoadingEntry(); - } else { - // Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act - // as if that was the fetched resource, ignoring the resource obtained from the network. - ASSERT(m_newestCache); - ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->firstRequest().url()); - ASSERT(newestCachedResource); - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); - m_pendingEntries.remove(m_currentHandle->firstRequest().url()); - m_currentHandle->cancel(); - m_currentHandle = 0; - // Load the next resource, if any. - startLoadingEntry(); - } - return; - } - - m_currentResource = ApplicationCacheResource::create(url, response, type); -} - -void ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived) -{ -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveContentLength(m_currentResourceIdentifier, lengthReceived); -#else - UNUSED_PARAM(lengthReceived); -#endif - - if (handle == m_manifestHandle) { - didReceiveManifestData(data, length); - return; - } - - ASSERT(handle == m_currentHandle); - - ASSERT(m_currentResource); - m_currentResource->data()->append(data, length); - - m_loadedSize += length; -} - -void ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle, double finishTime) -{ -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didFinishLoading(m_currentResourceIdentifier, finishTime); -#endif - - if (handle == m_manifestHandle) { - didFinishLoadingManifest(); - return; - } - - // After finishing the loading of any resource, we check if it will - // fit in our last known quota limit. - if (m_availableSpaceInQuota == ApplicationCacheStorage::unknownQuota()) { - // Failed to determine what is left in the quota. Fallback to allowing anything. - if (!cacheStorage().remainingSizeForOriginExcludingCache(m_origin.get(), m_newestCache.get(), m_availableSpaceInQuota)) - m_availableSpaceInQuota = ApplicationCacheStorage::noQuota(); - } - - // Check each resource, as it loads, to see if it would fit in our - // idea of the available quota space. - if (m_availableSpaceInQuota < m_loadedSize) { - m_currentResource = 0; - cacheUpdateFailedDueToOriginQuota(); - return; - } - - ASSERT(m_currentHandle == handle); - ASSERT(m_pendingEntries.contains(handle->firstRequest().url())); - - m_pendingEntries.remove(handle->firstRequest().url()); - - ASSERT(m_cacheBeingUpdated); - - m_cacheBeingUpdated->addResource(m_currentResource.release()); - m_currentHandle = 0; - - // Load the next resource, if any. - startLoadingEntry(); -} - -void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError& error) -{ -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didFailLoading(m_currentResourceIdentifier, error); -#else - UNUSED_PARAM(error); -#endif - - if (handle == m_manifestHandle) { - cacheUpdateFailed(); - return; - } - - unsigned type = m_currentResource ? m_currentResource->type() : m_pendingEntries.get(handle->firstRequest().url()); - KURL url(handle->firstRequest().url()); - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - ASSERT(!m_currentResource || !m_pendingEntries.contains(url)); - m_currentResource = 0; - m_pendingEntries.remove(url); - - if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) { - // Note that cacheUpdateFailed() can cause the cache group to be deleted. - cacheUpdateFailed(); - } else { - // Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act - // as if that was the fetched resource, ignoring the resource obtained from the network. - ASSERT(m_newestCache); - ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url); - ASSERT(newestCachedResource); - m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data())); - // Load the next resource, if any. - startLoadingEntry(); - } -} - -void ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& response) -{ - ASSERT(!m_manifestResource); - ASSERT(m_manifestHandle); - - if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) { - manifestNotFound(); - return; - } - - if (response.httpStatusCode() == 304) - return; - - if (response.httpStatusCode() / 100 != 2 || response.url() != m_manifestHandle->firstRequest().url() || !equalIgnoringCase(response.mimeType(), "text/cache-manifest")) { - cacheUpdateFailed(); - return; - } - - m_manifestResource = ApplicationCacheResource::create(m_manifestHandle->firstRequest().url(), response, ApplicationCacheResource::Manifest); -} - -void ApplicationCacheGroup::didReceiveManifestData(const char* data, int length) -{ - if (m_manifestResource) - m_manifestResource->data()->append(data, length); -} - -void ApplicationCacheGroup::didFinishLoadingManifest() -{ - bool isUpgradeAttempt = m_newestCache; - - if (!isUpgradeAttempt && !m_manifestResource) { - // The server returned 304 Not Modified even though we didn't send a conditional request. - cacheUpdateFailed(); - return; - } - - m_manifestHandle = 0; - - // Check if the manifest was not modified. - if (isUpgradeAttempt) { - ApplicationCacheResource* newestManifest = m_newestCache->manifestResource(); - ASSERT(newestManifest); - - if (!m_manifestResource || // The resource will be null if HTTP response was 304 Not Modified. - (newestManifest->data()->size() == m_manifestResource->data()->size() && !memcmp(newestManifest->data()->data(), m_manifestResource->data()->data(), newestManifest->data()->size()))) { - - m_completionType = NoUpdate; - m_manifestResource = 0; - deliverDelayedMainResources(); - - return; - } - } - - Manifest manifest; - if (!parseManifest(m_manifestURL, m_manifestResource->data()->data(), m_manifestResource->data()->size(), manifest)) { - cacheUpdateFailed(); - return; - } - - ASSERT(!m_cacheBeingUpdated); - m_cacheBeingUpdated = ApplicationCache::create(); - m_cacheBeingUpdated->setGroup(this); - - HashSet<DocumentLoader*>::const_iterator masterEnd = m_pendingMasterResourceLoaders.end(); - for (HashSet<DocumentLoader*>::const_iterator iter = m_pendingMasterResourceLoaders.begin(); iter != masterEnd; ++iter) - associateDocumentLoaderWithCache(*iter, m_cacheBeingUpdated.get()); - - // We have the manifest, now download the resources. - setUpdateStatus(Downloading); - - postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders); - - ASSERT(m_pendingEntries.isEmpty()); - - if (isUpgradeAttempt) { - 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::Master) - 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); - - size_t fallbackCount = manifest.fallbackURLs.size(); - for (size_t i = 0; i < fallbackCount; ++i) - addEntry(manifest.fallbackURLs[i].second, ApplicationCacheResource::Fallback); - - m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs); - m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs); - m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests); - - m_progressTotal = m_pendingEntries.size(); - m_progressDone = 0; - - startLoadingEntry(); -} - -void ApplicationCacheGroup::didReachMaxAppCacheSize() -{ - ASSERT(m_frame); - ASSERT(m_cacheBeingUpdated); - m_frame->page()->chrome()->client()->reachedMaxAppCacheSize(cacheStorage().spaceNeeded(m_cacheBeingUpdated->estimatedSizeInStorage())); - m_calledReachedMaxAppCacheSize = true; - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::didReachOriginQuota(PassRefPtr<Frame> frame) -{ - // Inform the client the origin quota has been reached, - // they may decide to increase the quota. - frame->page()->chrome()->client()->reachedApplicationCacheOriginQuota(m_origin.get()); -} - -void ApplicationCacheGroup::cacheUpdateFailed() -{ - stopLoading(); - m_manifestResource = 0; - - // Wait for master resource loads to finish. - m_completionType = Failure; - deliverDelayedMainResources(); -} - -void ApplicationCacheGroup::cacheUpdateFailedDueToOriginQuota() -{ - if (!m_originQuotaReached) { - m_originQuotaReached = true; - scheduleReachedOriginQuotaCallback(); - } - - cacheUpdateFailed(); -} - -void ApplicationCacheGroup::manifestNotFound() -{ - makeObsolete(); - - postListenerTask(ApplicationCacheHost::OBSOLETE_EVENT, m_associatedDocumentLoaders); - postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_pendingMasterResourceLoaders); - - stopLoading(); - - ASSERT(m_pendingEntries.isEmpty()); - m_manifestResource = 0; - - while (!m_pendingMasterResourceLoaders.isEmpty()) { - HashSet<DocumentLoader*>::iterator it = m_pendingMasterResourceLoaders.begin(); - - ASSERT((*it)->applicationCacheHost()->candidateApplicationCacheGroup() == this); - ASSERT(!(*it)->applicationCacheHost()->applicationCache()); - (*it)->applicationCacheHost()->setCandidateApplicationCacheGroup(0); - m_pendingMasterResourceLoaders.remove(it); - } - - m_downloadingPendingMasterResourceLoadersCount = 0; - setUpdateStatus(Idle); - m_frame = 0; - - if (m_caches.isEmpty()) { - ASSERT(m_associatedDocumentLoaders.isEmpty()); - ASSERT(!m_cacheBeingUpdated); - delete this; - } -} - -void ApplicationCacheGroup::checkIfLoadIsComplete() -{ - if (m_manifestHandle || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount) - return; - - // We're done, all resources have finished downloading (successfully or not). - - bool isUpgradeAttempt = m_newestCache; - - switch (m_completionType) { - case None: - ASSERT_NOT_REACHED(); - return; - case NoUpdate: - ASSERT(isUpgradeAttempt); - ASSERT(!m_cacheBeingUpdated); - - // The storage could have been manually emptied by the user. - if (!m_storageID) - cacheStorage().storeNewestCache(this); - - postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, m_associatedDocumentLoaders); - break; - case Failure: - ASSERT(!m_cacheBeingUpdated); - postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders); - if (m_caches.isEmpty()) { - ASSERT(m_associatedDocumentLoaders.isEmpty()); - delete this; - return; - } - break; - case Completed: { - // FIXME: Fetch the resource from manifest URL again, and check whether it is identical to the one used for update (in case the application was upgraded server-side in the meanwhile). (<rdar://problem/6467625>) - - ASSERT(m_cacheBeingUpdated); - if (m_manifestResource) - m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); - else { - // We can get here as a result of retrying the Complete step, following - // a failure of the cache storage to save the newest cache due to hitting - // the maximum size. In such a case, m_manifestResource may be 0, as - // the manifest was already set on the newest cache object. - ASSERT(cacheStorage().isMaximumSizeReached() && m_calledReachedMaxAppCacheSize); - } - - ApplicationCacheStorage::FailureReason failureReason; - RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? 0 : m_newestCache; - setNewestCache(m_cacheBeingUpdated.release()); - if (cacheStorage().storeNewestCache(this, oldNewestCache.get(), failureReason)) { - // New cache stored, now remove the old cache. - if (oldNewestCache) - cacheStorage().remove(oldNewestCache.get()); - - // Fire the final progress event. - ASSERT(m_progressDone == m_progressTotal); - postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_progressTotal, m_progressDone, m_associatedDocumentLoaders); - - // Fire the success event. - postListenerTask(isUpgradeAttempt ? ApplicationCacheHost::UPDATEREADY_EVENT : ApplicationCacheHost::CACHED_EVENT, m_associatedDocumentLoaders); - // It is clear that the origin quota was not reached, so clear the flag if it was set. - m_originQuotaReached = false; - } else { - if (failureReason == ApplicationCacheStorage::OriginQuotaReached) { - // We ran out of space for this origin. Roll back to previous state. - if (oldNewestCache) - setNewestCache(oldNewestCache.release()); - cacheUpdateFailedDueToOriginQuota(); - return; - } - - if (failureReason == ApplicationCacheStorage::TotalQuotaReached && !m_calledReachedMaxAppCacheSize) { - // We ran out of space. All the changes in the cache storage have - // been rolled back. We roll back to the previous state in here, - // as well, call the chrome client asynchronously and retry to - // save the new cache. - - // Save a reference to the new cache. - m_cacheBeingUpdated = m_newestCache.release(); - if (oldNewestCache) { - // Reinstate the oldNewestCache. - setNewestCache(oldNewestCache.release()); - } - scheduleReachedMaxAppCacheSizeCallback(); - return; - } - - // Run the "cache failure steps" - // Fire the error events to all pending master entries, as well any other cache hosts - // currently associated with a cache in this group. - postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders); - // Disassociate the pending master entries from the failed new cache. Note that - // all other loaders in the m_associatedDocumentLoaders are still associated with - // some other cache in this group. They are not associated with the failed new cache. - - // Need to copy loaders, because the cache group may be destroyed at the end of iteration. - Vector<DocumentLoader*> loaders; - copyToVector(m_pendingMasterResourceLoaders, loaders); - size_t count = loaders.size(); - for (size_t i = 0; i != count; ++i) - disassociateDocumentLoader(loaders[i]); // This can delete this group. - - // Reinstate the oldNewestCache, if there was one. - if (oldNewestCache) { - // This will discard the failed new cache. - setNewestCache(oldNewestCache.release()); - } else { - // We must have been deleted by the last call to disassociateDocumentLoader(). - return; - } - } - break; - } - } - - // Empty cache group's list of pending master entries. - m_pendingMasterResourceLoaders.clear(); - m_completionType = None; - setUpdateStatus(Idle); - m_frame = 0; - m_loadedSize = 0; - m_availableSpaceInQuota = ApplicationCacheStorage::unknownQuota(); - m_calledReachedMaxAppCacheSize = false; -} - -void ApplicationCacheGroup::startLoadingEntry() -{ - ASSERT(m_cacheBeingUpdated); - - if (m_pendingEntries.isEmpty()) { - m_completionType = Completed; - deliverDelayedMainResources(); - return; - } - - EntryMap::const_iterator it = m_pendingEntries.begin(); - - postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_progressTotal, m_progressDone, m_associatedDocumentLoaders); - m_progressDone++; - - ASSERT(!m_currentHandle); - - m_currentHandle = createResourceHandle(KURL(ParsedURLString, it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0); -} - -void ApplicationCacheGroup::deliverDelayedMainResources() -{ - // Need to copy loaders, because the cache group may be destroyed at the end of iteration. - Vector<DocumentLoader*> loaders; - copyToVector(m_pendingMasterResourceLoaders, loaders); - size_t count = loaders.size(); - for (size_t i = 0; i != count; ++i) { - DocumentLoader* loader = loaders[i]; - if (loader->isLoadingMainResource()) - continue; - - const ResourceError& error = loader->mainDocumentError(); - if (error.isNull()) - finishedLoadingMainResource(loader); - else - failedLoadingMainResource(loader); - } - if (!count) - checkIfLoadIsComplete(); -} - -void ApplicationCacheGroup::addEntry(const String& url, unsigned type) -{ - ASSERT(m_cacheBeingUpdated); - ASSERT(!KURL(ParsedURLString, url).hasFragmentIdentifier()); - - // Don't add the URL if we already have an master resource in the cache - // (i.e., the main resource finished loading before the manifest). - if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) { - ASSERT(resource->type() & ApplicationCacheResource::Master); - ASSERT(!m_frame->loader()->documentLoader()->isLoadingMainResource()); - - resource->addType(type); - return; - } - - // Don't add the URL if it's the same as the manifest URL. - ASSERT(m_manifestResource); - if (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) -{ - // If teardown started already, revive the group. - if (!m_newestCache && !m_cacheBeingUpdated) - m_newestCache = cache; - - ASSERT(!m_isObsolete); - - loader->applicationCacheHost()->setApplicationCache(cache); - - ASSERT(!m_associatedDocumentLoaders.contains(loader)); - m_associatedDocumentLoaders.add(loader); -} - -class ChromeClientCallbackTimer: public TimerBase { -public: - ChromeClientCallbackTimer(ApplicationCacheGroup* cacheGroup) - : m_cacheGroup(cacheGroup) - { - } - -private: - virtual void fired() - { - m_cacheGroup->didReachMaxAppCacheSize(); - delete this; - } - // Note that there is no need to use a RefPtr here. The ApplicationCacheGroup instance is guaranteed - // to be alive when the timer fires since invoking the ChromeClient callback is part of its normal - // update machinery and nothing can yet cause it to get deleted. - ApplicationCacheGroup* m_cacheGroup; -}; - -void ApplicationCacheGroup::scheduleReachedMaxAppCacheSizeCallback() -{ - ASSERT(isMainThread()); - ChromeClientCallbackTimer* timer = new ChromeClientCallbackTimer(this); - timer->startOneShot(0); - // The timer will delete itself once it fires. -} - -void ApplicationCacheGroup::scheduleReachedOriginQuotaCallback() -{ - // FIXME: it might be nice to run this asynchronously, because there is no return value to wait for. - didReachOriginQuota(m_frame); -} - -class CallCacheListenerTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<CallCacheListenerTask> create(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone) - { - return adoptPtr(new CallCacheListenerTask(loader, eventID, progressTotal, progressDone)); - } - - virtual void performTask(ScriptExecutionContext* context) - { - - ASSERT_UNUSED(context, context->isDocument()); - Frame* frame = m_documentLoader->frame(); - if (!frame) - return; - - ASSERT(frame->loader()->documentLoader() == m_documentLoader.get()); - - m_documentLoader->applicationCacheHost()->notifyDOMApplicationCache(m_eventID, m_progressTotal, m_progressDone); - } - -private: - CallCacheListenerTask(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone) - : m_documentLoader(loader) - , m_eventID(eventID) - , m_progressTotal(progressTotal) - , m_progressDone(progressDone) - { - } - - RefPtr<DocumentLoader> m_documentLoader; - ApplicationCacheHost::EventID m_eventID; - int m_progressTotal; - int m_progressDone; -}; - -void ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone, const HashSet<DocumentLoader*>& loaderSet) -{ - HashSet<DocumentLoader*>::const_iterator loaderSetEnd = loaderSet.end(); - for (HashSet<DocumentLoader*>::const_iterator iter = loaderSet.begin(); iter != loaderSetEnd; ++iter) - postListenerTask(eventID, progressTotal, progressDone, *iter); -} - -void ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone, DocumentLoader* loader) -{ - Frame* frame = loader->frame(); - if (!frame) - return; - - ASSERT(frame->loader()->documentLoader() == loader); - - frame->document()->postTask(CallCacheListenerTask::create(loader, eventID, progressTotal, progressDone)); -} - -void ApplicationCacheGroup::setUpdateStatus(UpdateStatus status) -{ - m_updateStatus = status; -#if ENABLE(INSPECTOR) - inspectorUpdateApplicationCacheStatus(m_frame); -#endif -} - -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 29d0749..0000000 --- a/WebCore/loader/appcache/ApplicationCacheGroup.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 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 "DOMApplicationCache.h" -#include "KURL.h" -#include "PlatformString.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "SharedBuffer.h" - -#include <wtf/Noncopyable.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> - -namespace WebCore { - -class ApplicationCache; -class ApplicationCacheResource; -class Document; -class DocumentLoader; -class Frame; -class SecurityOrigin; - -enum ApplicationCacheUpdateOption { - ApplicationCacheUpdateWithBrowsingContext, - ApplicationCacheUpdateWithoutBrowsingContext -}; - -class ApplicationCacheGroup : public Noncopyable, ResourceHandleClient { -public: - ApplicationCacheGroup(const KURL& manifestURL, bool isCopy = false); - ~ApplicationCacheGroup(); - - enum UpdateStatus { Idle, Checking, Downloading }; - - static ApplicationCache* cacheForMainRequest(const ResourceRequest&, DocumentLoader*); - static ApplicationCache* fallbackCacheForMainRequest(const ResourceRequest&, DocumentLoader*); - - static void selectCache(Frame*, const KURL& manifestURL); - static void selectCacheWithoutManifestURL(Frame*); - - const KURL& manifestURL() const { return m_manifestURL; } - const SecurityOrigin* origin() const { return m_origin.get(); } - UpdateStatus updateStatus() const { return m_updateStatus; } - void setUpdateStatus(UpdateStatus status); - - void setStorageID(unsigned storageID) { m_storageID = storageID; } - unsigned storageID() const { return m_storageID; } - void clearStorageID(); - - void update(Frame*, ApplicationCacheUpdateOption); // FIXME: Frame should not be needed when updating without browsing context. - void cacheDestroyed(ApplicationCache*); - - bool cacheIsBeingUpdated(const ApplicationCache* cache) const { return cache == m_cacheBeingUpdated; } - - void stopLoadingInFrame(Frame*); - - ApplicationCache* newestCache() const { return m_newestCache.get(); } - void setNewestCache(PassRefPtr<ApplicationCache>); - - void makeObsolete(); - bool isObsolete() const { return m_isObsolete; } - - void finishedLoadingMainResource(DocumentLoader*); - void failedLoadingMainResource(DocumentLoader*); - - void disassociateDocumentLoader(DocumentLoader*); - - bool isCopy() const { return m_isCopy; } - -private: - static void postListenerTask(ApplicationCacheHost::EventID id, const HashSet<DocumentLoader*>& set) { postListenerTask(id, 0, 0, set); } - static void postListenerTask(ApplicationCacheHost::EventID id, DocumentLoader* loader) { postListenerTask(id, 0, 0, loader); } - static void postListenerTask(ApplicationCacheHost::EventID, int progressTotal, int progressDone, const HashSet<DocumentLoader*>&); - static void postListenerTask(ApplicationCacheHost::EventID, int progressTotal, int progressDone, DocumentLoader*); - - void scheduleReachedMaxAppCacheSizeCallback(); - void scheduleReachedOriginQuotaCallback(); - - PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource); - - // For normal resource loading, WebKit client is asked about each resource individually. Since application cache does not belong to any particular document, - // the existing client callback cannot be used, so assume that any client that enables application cache also wants it to use credential storage. - virtual bool shouldUseCredentialStorage(ResourceHandle*) { return true; } - -#if ENABLE(INSPECTOR) - virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&); -#endif - virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); - virtual void didReceiveData(ResourceHandle*, const char*, int length, int lengthReceived); - virtual void didFinishLoading(ResourceHandle*, double finishTime); - virtual void didFail(ResourceHandle*, const ResourceError&); - - void didReceiveManifestResponse(const ResourceResponse&); - void didReceiveManifestData(const char*, int); - void didFinishLoadingManifest(); - void didReachMaxAppCacheSize(); - void didReachOriginQuota(PassRefPtr<Frame> frame); - - void startLoadingEntry(); - void deliverDelayedMainResources(); - void checkIfLoadIsComplete(); - void cacheUpdateFailed(); - void cacheUpdateFailedDueToOriginQuota(); - void manifestNotFound(); - - void addEntry(const String&, unsigned type); - - void associateDocumentLoaderWithCache(DocumentLoader*, ApplicationCache*); - - void stopLoading(); - - KURL m_manifestURL; - RefPtr<SecurityOrigin> m_origin; - UpdateStatus m_updateStatus; - - // This is the newest complete cache in the group. - RefPtr<ApplicationCache> m_newestCache; - - // All complete caches in this cache group. - HashSet<ApplicationCache*> m_caches; - - // The cache being updated (if any). Note that cache updating does not immediately create a new - // ApplicationCache object, so this may be null even when update status is not Idle. - RefPtr<ApplicationCache> m_cacheBeingUpdated; - - // List of pending master entries, used during the update process to ensure that new master entries are cached. - HashSet<DocumentLoader*> m_pendingMasterResourceLoaders; - // How many of the above pending master entries have not yet finished downloading. - int m_downloadingPendingMasterResourceLoadersCount; - - // 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; - - // The total number of items to be processed to update the cache group and the number that have been done. - int m_progressTotal; - int m_progressDone; - - // Frame used for fetching resources when updating. - // FIXME: An update started by a particular frame should not stop if it is destroyed, but there are other frames associated with the same cache group. - Frame* m_frame; - - // An obsolete cache group is never stored, but the opposite is not true - storing may fail for multiple reasons, such as exceeding disk quota. - unsigned m_storageID; - bool m_isObsolete; - - // During update, this is used to handle asynchronously arriving results. - enum CompletionType { - None, - NoUpdate, - Failure, - Completed - }; - CompletionType m_completionType; - - // Whether this cache group is a copy that's only used for transferring the cache to another file. - bool m_isCopy; - - // This flag is set immediately after the ChromeClient::reachedMaxAppCacheSize() callback is invoked as a result of the storage layer failing to save a cache - // due to reaching the maximum size of the application cache database file. This flag is used by ApplicationCacheGroup::checkIfLoadIsComplete() to decide - // the course of action in case of this failure (i.e. call the ChromeClient callback or run the failure steps). - bool m_calledReachedMaxAppCacheSize; - - RefPtr<ResourceHandle> m_currentHandle; - RefPtr<ApplicationCacheResource> m_currentResource; - -#if ENABLE(INSPECTOR) - unsigned long m_currentResourceIdentifier; -#endif - - RefPtr<ApplicationCacheResource> m_manifestResource; - RefPtr<ResourceHandle> m_manifestHandle; - - int64_t m_loadedSize; - int64_t m_availableSpaceInQuota; - bool m_originQuotaReached; - - friend class ChromeClientCallbackTimer; - friend class OriginQuotaReachedCallbackTimer; -}; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) - -#endif // ApplicationCacheGroup_h diff --git a/WebCore/loader/appcache/ApplicationCacheHost.cpp b/WebCore/loader/appcache/ApplicationCacheHost.cpp deleted file mode 100644 index d5707cf..0000000 --- a/WebCore/loader/appcache/ApplicationCacheHost.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "ApplicationCacheHost.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCache.h" -#include "ApplicationCacheGroup.h" -#include "ApplicationCacheResource.h" -#include "DocumentLoader.h" -#include "DOMApplicationCache.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "MainResourceLoader.h" -#include "ProgressEvent.h" -#include "ResourceLoader.h" -#include "ResourceRequest.h" -#include "Settings.h" - -namespace WebCore { - -ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader) - : m_domApplicationCache(0) - , m_documentLoader(documentLoader) - , m_defersEvents(true) - , m_candidateApplicationCacheGroup(0) -{ - ASSERT(m_documentLoader); -} - -ApplicationCacheHost::~ApplicationCacheHost() -{ - ASSERT(!m_applicationCache || !m_candidateApplicationCacheGroup || m_applicationCache->group() == m_candidateApplicationCacheGroup); - - if (m_applicationCache) - m_applicationCache->group()->disassociateDocumentLoader(m_documentLoader); - else if (m_candidateApplicationCacheGroup) - m_candidateApplicationCacheGroup->disassociateDocumentLoader(m_documentLoader); -} - -void ApplicationCacheHost::selectCacheWithoutManifest() -{ - ApplicationCacheGroup::selectCacheWithoutManifestURL(m_documentLoader->frame()); -} - -void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL) -{ - ApplicationCacheGroup::selectCache(m_documentLoader->frame(), manifestURL); -} - -void ApplicationCacheHost::maybeLoadMainResource(ResourceRequest& request, SubstituteData& substituteData) -{ - // Check if this request should be loaded from the application cache - if (!substituteData.isValid() && isApplicationCacheEnabled()) { - ASSERT(!m_mainResourceApplicationCache); - - m_mainResourceApplicationCache = ApplicationCacheGroup::cacheForMainRequest(request, m_documentLoader); - - if (m_mainResourceApplicationCache) { - // Get the resource from the application cache. By definition, cacheForMainRequest() returns a cache that contains the resource. - ApplicationCacheResource* resource = m_mainResourceApplicationCache->resourceForRequest(request); - substituteData = SubstituteData(resource->data(), - resource->response().mimeType(), - resource->response().textEncodingName(), KURL()); - } - } -} - -void ApplicationCacheHost::maybeLoadMainResourceForRedirect(ResourceRequest& request, SubstituteData& substituteData) -{ - ASSERT(status() == UNCACHED); - maybeLoadMainResource(request, substituteData); -} - -bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest& request, const ResourceResponse& r) -{ - if (r.httpStatusCode() / 100 == 4 || r.httpStatusCode() / 100 == 5) { - ASSERT(!m_mainResourceApplicationCache); - if (isApplicationCacheEnabled()) { - m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, documentLoader()); - - if (scheduleLoadFallbackResourceFromApplicationCache(documentLoader()->mainResourceLoader(), m_mainResourceApplicationCache.get())) - return true; - } - } - return false; -} - -bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest& request, const ResourceError& error) -{ - if (!error.isCancellation()) { - ASSERT(!m_mainResourceApplicationCache); - if (isApplicationCacheEnabled()) { - m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, m_documentLoader); - - if (scheduleLoadFallbackResourceFromApplicationCache(documentLoader()->mainResourceLoader(), m_mainResourceApplicationCache.get())) - return true; - } - } - return false; -} - -void ApplicationCacheHost::mainResourceDataReceived(const char*, int, long long, bool) -{ - // This method is here to facilitate alternate implemetations of this interface by the host browser. -} - -void ApplicationCacheHost::failedLoadingMainResource() -{ - ApplicationCacheGroup* group = m_candidateApplicationCacheGroup; - if (!group && m_applicationCache) { - if (mainResourceApplicationCache()) { - // Even when the main resource is being loaded from an application cache, loading can fail if aborted. - return; - } - group = m_applicationCache->group(); - } - - if (group) - group->failedLoadingMainResource(m_documentLoader); -} - -void ApplicationCacheHost::finishedLoadingMainResource() -{ - ApplicationCacheGroup* group = candidateApplicationCacheGroup(); - if (!group && applicationCache() && !mainResourceApplicationCache()) - group = applicationCache()->group(); - - if (group) - group->finishedLoadingMainResource(m_documentLoader); -} - -bool ApplicationCacheHost::maybeLoadResource(ResourceLoader* loader, ResourceRequest& request, const KURL& originalURL) -{ - if (!isApplicationCacheEnabled()) - return false; - - if (request.url() != originalURL) - return false; - - ApplicationCacheResource* resource; - if (!shouldLoadResourceFromApplicationCache(request, resource)) - return false; - - m_documentLoader->m_pendingSubstituteResources.set(loader, resource); - m_documentLoader->deliverSubstituteResourcesAfterDelay(); - - return true; -} - -bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader* resourceLoader, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - if (!redirectResponse.isNull() && !protocolHostAndPortAreEqual(request.url(), redirectResponse.url())) - if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader)) - return true; - return false; -} - -bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader* resourceLoader, const ResourceResponse& response) -{ - if (response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5) - if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader)) - return true; - return false; -} - -bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader* resourceLoader, const ResourceError& error) -{ - if (!error.isCancellation()) - if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader)) - return true; - return false; -} - -bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data) -{ - ApplicationCacheResource* resource; - if (shouldLoadResourceFromApplicationCache(request, resource)) { - if (resource) { - response = resource->response(); - data.append(resource->data()->data(), resource->data()->size()); - } else { - error = documentLoader()->frameLoader()->client()->cannotShowURLError(request); - } - return true; - } - return false; -} - -void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data) -{ - // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent, - // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry - // corresponding to the matched namespace. - if ((!error.isNull() && !error.isCancellation()) - || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5 - || !protocolHostAndPortAreEqual(request.url(), response.url())) { - ApplicationCacheResource* resource; - if (getApplicationCacheFallbackResource(request, resource)) { - response = resource->response(); - data.clear(); - data.append(resource->data()->data(), resource->data()->size()); - } - } -} - -bool ApplicationCacheHost::canCacheInPageCache() const -{ - return !applicationCache() && !candidateApplicationCacheGroup(); -} - -void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache) -{ - ASSERT(!m_domApplicationCache || !domApplicationCache); - m_domApplicationCache = domApplicationCache; -} - -void ApplicationCacheHost::notifyDOMApplicationCache(EventID id, int total, int done) -{ - if (m_defersEvents) { - // Event dispatching is deferred until document.onload has fired. - m_deferredEvents.append(DeferredEvent(id, total, done)); - return; - } - dispatchDOMEvent(id, total, done); -} - -void ApplicationCacheHost::stopLoadingInFrame(Frame* frame) -{ - ASSERT(!m_applicationCache || !m_candidateApplicationCacheGroup || m_applicationCache->group() == m_candidateApplicationCacheGroup); - - if (m_candidateApplicationCacheGroup) - m_candidateApplicationCacheGroup->stopLoadingInFrame(frame); - else if (m_applicationCache) - m_applicationCache->group()->stopLoadingInFrame(frame); -} - -void ApplicationCacheHost::stopDeferringEvents() -{ - RefPtr<DocumentLoader> protect(documentLoader()); - for (unsigned i = 0; i < m_deferredEvents.size(); ++i) { - const DeferredEvent& deferred = m_deferredEvents[i]; - dispatchDOMEvent(deferred.eventID, deferred.progressTotal, deferred.progressDone); - } - m_deferredEvents.clear(); - m_defersEvents = false; -} - -#if ENABLE(INSPECTOR) -void ApplicationCacheHost::fillResourceList(ResourceInfoList* resources) -{ - ApplicationCache* cache = applicationCache(); - if (!cache || !cache->isComplete()) - return; - - ApplicationCache::ResourceMap::const_iterator end = cache->end(); - for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { - RefPtr<ApplicationCacheResource> resource = it->second; - unsigned type = resource->type(); - bool isMaster = type & ApplicationCacheResource::Master; - bool isManifest = type & ApplicationCacheResource::Manifest; - bool isExplicit = type & ApplicationCacheResource::Explicit; - bool isForeign = type & ApplicationCacheResource::Foreign; - bool isFallback = type & ApplicationCacheResource::Fallback; - resources->append(ResourceInfo(resource->url(), isMaster, isManifest, isFallback, isForeign, isExplicit, resource->estimatedSizeInStorage())); - } -} - -ApplicationCacheHost::CacheInfo ApplicationCacheHost::applicationCacheInfo() -{ - ApplicationCache* cache = applicationCache(); - if (!cache || !cache->isComplete()) - return CacheInfo(KURL(), 0, 0, 0); - - // FIXME: Add "Creation Time" and "Update Time" to Application Caches. - return CacheInfo(cache->manifestResource()->url(), 0, 0, cache->estimatedSizeInStorage()); -} -#endif - -void ApplicationCacheHost::dispatchDOMEvent(EventID id, int total, int done) -{ - if (m_domApplicationCache) { - const AtomicString& eventType = DOMApplicationCache::toEventType(id); - ExceptionCode ec = 0; - RefPtr<Event> event; - if (id == PROGRESS_EVENT) - event = ProgressEvent::create(eventType, true, done, total); - else - event = Event::create(eventType, false, false); - m_domApplicationCache->dispatchEvent(event, ec); - ASSERT(!ec); - } -} - -void ApplicationCacheHost::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group) -{ - ASSERT(!m_applicationCache); - m_candidateApplicationCacheGroup = group; -} - -void ApplicationCacheHost::setApplicationCache(PassRefPtr<ApplicationCache> applicationCache) -{ - if (m_candidateApplicationCacheGroup) { - ASSERT(!m_applicationCache); - m_candidateApplicationCacheGroup = 0; - } - - m_applicationCache = applicationCache; -} - -bool ApplicationCacheHost::shouldLoadResourceFromApplicationCache(const ResourceRequest& request, ApplicationCacheResource*& resource) -{ - ApplicationCache* cache = applicationCache(); - if (!cache || !cache->isComplete()) - return false; - - // If the resource is not to be fetched using the HTTP GET mechanism or equivalent, or if its URL has a different - // <scheme> component than the application cache's manifest, then fetch the resource normally. - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request) || !equalIgnoringCase(request.url().protocol(), cache->manifestResource()->url().protocol())) - return false; - - // If the resource's URL is an master entry, the manifest, an explicit entry, or a fallback entry - // in the application cache, then get the resource from the cache (instead of fetching it). - resource = cache->resourceForURL(request.url()); - - // Resources that match fallback namespaces or online whitelist entries are fetched from the network, - // unless they are also cached. - if (!resource && (cache->urlMatchesFallbackNamespace(request.url()) || cache->isURLInOnlineWhitelist(request.url()))) - return false; - - // Resources that are not present in the manifest will always fail to load (at least, after the - // cache has been primed the first time), making the testing of offline applications simpler. - return true; -} - -bool ApplicationCacheHost::getApplicationCacheFallbackResource(const ResourceRequest& request, ApplicationCacheResource*& resource, ApplicationCache* cache) -{ - if (!cache) { - cache = applicationCache(); - if (!cache) - return false; - } - if (!cache->isComplete()) - return false; - - // If the resource is not a HTTP/HTTPS GET, then abort - if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request)) - return false; - - KURL fallbackURL; - if (!cache->urlMatchesFallbackNamespace(request.url(), &fallbackURL)) - return false; - - resource = cache->resourceForURL(fallbackURL); - ASSERT(resource); - - return true; -} - -bool ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader* loader, ApplicationCache* cache) -{ - if (!isApplicationCacheEnabled()) - return false; - - ApplicationCacheResource* resource; - if (!getApplicationCacheFallbackResource(loader->request(), resource, cache)) - return false; - - m_documentLoader->m_pendingSubstituteResources.set(loader, resource); - m_documentLoader->deliverSubstituteResourcesAfterDelay(); - - loader->handle()->cancel(); - - return true; -} - -ApplicationCacheHost::Status ApplicationCacheHost::status() const -{ - ApplicationCache* cache = applicationCache(); - if (!cache) - return UNCACHED; - - switch (cache->group()->updateStatus()) { - case ApplicationCacheGroup::Checking: - return CHECKING; - case ApplicationCacheGroup::Downloading: - return DOWNLOADING; - case ApplicationCacheGroup::Idle: { - if (cache->group()->isObsolete()) - return OBSOLETE; - if (cache != cache->group()->newestCache()) - return UPDATEREADY; - return IDLE; - } - } - - ASSERT_NOT_REACHED(); - return UNCACHED; -} - -bool ApplicationCacheHost::update() -{ - ApplicationCache* cache = applicationCache(); - if (!cache) - return false; - cache->group()->update(m_documentLoader->frame(), ApplicationCacheUpdateWithoutBrowsingContext); - return true; -} - -bool ApplicationCacheHost::swapCache() -{ - ApplicationCache* cache = applicationCache(); - if (!cache) - return false; - - // If the group of application caches to which cache belongs has the lifecycle status obsolete, unassociate document from cache. - if (cache->group()->isObsolete()) { - cache->group()->disassociateDocumentLoader(m_documentLoader); - return true; - } - - // If there is no newer cache, raise an INVALID_STATE_ERR exception. - ApplicationCache* newestCache = cache->group()->newestCache(); - if (cache == newestCache) - return false; - - ASSERT(cache->group() == newestCache->group()); - setApplicationCache(newestCache); - - return true; -} - -bool ApplicationCacheHost::isApplicationCacheEnabled() -{ - return m_documentLoader->frame()->settings() - && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled(); -} - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/loader/appcache/ApplicationCacheHost.h b/WebCore/loader/appcache/ApplicationCacheHost.h deleted file mode 100644 index 8ac5357..0000000 --- a/WebCore/loader/appcache/ApplicationCacheHost.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2009, Google 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER 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 ApplicationCacheHost_h -#define ApplicationCacheHost_h - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "KURL.h" -#include <wtf/Deque.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - class DOMApplicationCache; - class DocumentLoader; - class Frame; - class ResourceLoader; - class ResourceError; - class ResourceRequest; - class ResourceResponse; - class SubstituteData; -#if PLATFORM(CHROMIUM) - class ApplicationCacheHostInternal; -#else - class ApplicationCache; - class ApplicationCacheGroup; - class ApplicationCacheResource; - class ApplicationCacheStorage; -#endif - - class ApplicationCacheHost : public Noncopyable { - public: - // The Status numeric values are specified in the HTML5 spec. - enum Status { - UNCACHED = 0, - IDLE = 1, - CHECKING = 2, - DOWNLOADING = 3, - UPDATEREADY = 4, - OBSOLETE = 5 - }; - - enum EventID { - CHECKING_EVENT = 0, - ERROR_EVENT, - NOUPDATE_EVENT, - DOWNLOADING_EVENT, - PROGRESS_EVENT, - UPDATEREADY_EVENT, - CACHED_EVENT, - OBSOLETE_EVENT // Must remain the last value, this is used to size arrays. - }; - -#if ENABLE(INSPECTOR) - struct CacheInfo { - CacheInfo(const KURL& manifest, double creationTime, double updateTime, long long size) - : m_manifest(manifest) - , m_creationTime(creationTime) - , m_updateTime(updateTime) - , m_size(size) { } - KURL m_manifest; - double m_creationTime; - double m_updateTime; - long long m_size; - }; - - struct ResourceInfo { - ResourceInfo(const KURL& resource, bool isMaster, bool isManifest, bool isFallback, bool isForeign, bool isExplicit, long long size) - : m_resource(resource) - , m_isMaster(isMaster) - , m_isManifest(isManifest) - , m_isFallback(isFallback) - , m_isForeign(isForeign) - , m_isExplicit(isExplicit) - , m_size(size) { } - KURL m_resource; - bool m_isMaster; - bool m_isManifest; - bool m_isFallback; - bool m_isForeign; - bool m_isExplicit; - long long m_size; - }; - - typedef Vector<ResourceInfo> ResourceInfoList; -#endif - - ApplicationCacheHost(DocumentLoader*); - ~ApplicationCacheHost(); - - void selectCacheWithoutManifest(); - void selectCacheWithManifest(const KURL& manifestURL); - - void maybeLoadMainResource(ResourceRequest&, SubstituteData&); - void maybeLoadMainResourceForRedirect(ResourceRequest&, SubstituteData&); - bool maybeLoadFallbackForMainResponse(const ResourceRequest&, const ResourceResponse&); - bool maybeLoadFallbackForMainError(const ResourceRequest&, const ResourceError&); - void mainResourceDataReceived(const char* data, int length, long long lengthReceived, bool allAtOnce); - void finishedLoadingMainResource(); - void failedLoadingMainResource(); - - bool maybeLoadResource(ResourceLoader*, ResourceRequest&, const KURL& originalURL); - bool maybeLoadFallbackForRedirect(ResourceLoader*, ResourceRequest&, const ResourceResponse&); - bool maybeLoadFallbackForResponse(ResourceLoader*, const ResourceResponse&); - bool maybeLoadFallbackForError(ResourceLoader*, const ResourceError&); - - bool maybeLoadSynchronously(ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data); - void maybeLoadFallbackSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data); - - bool canCacheInPageCache() const; - - Status status() const; - bool update(); - bool swapCache(); - - void setDOMApplicationCache(DOMApplicationCache*); - void notifyDOMApplicationCache(EventID, int progressTotal, int progressDone); - - void stopLoadingInFrame(Frame*); - - void stopDeferringEvents(); // Also raises the events that have been queued up. - -#if ENABLE(INSPECTOR) - void fillResourceList(ResourceInfoList*); - CacheInfo applicationCacheInfo(); -#endif - - private: - bool isApplicationCacheEnabled(); - DocumentLoader* documentLoader() const { return m_documentLoader; } - - struct DeferredEvent { - EventID eventID; - int progressTotal; - int progressDone; - DeferredEvent(EventID id, int total, int done) : eventID(id), progressTotal(total), progressDone(done) { } - }; - - DOMApplicationCache* m_domApplicationCache; - DocumentLoader* m_documentLoader; - bool m_defersEvents; // Events are deferred until after document onload. - Vector<DeferredEvent> m_deferredEvents; - - void dispatchDOMEvent(EventID, int progressTotal, int progressDone); - -#if PLATFORM(CHROMIUM) - friend class ApplicationCacheHostInternal; - OwnPtr<ApplicationCacheHostInternal> m_internal; -#else - friend class ApplicationCacheGroup; - friend class ApplicationCacheStorage; - - bool scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader*, ApplicationCache* = 0); - bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&); - bool getApplicationCacheFallbackResource(const ResourceRequest&, ApplicationCacheResource*&, ApplicationCache* = 0); - void setCandidateApplicationCacheGroup(ApplicationCacheGroup* group); - ApplicationCacheGroup* candidateApplicationCacheGroup() const { return m_candidateApplicationCacheGroup; } - void setApplicationCache(PassRefPtr<ApplicationCache> applicationCache); - ApplicationCache* applicationCache() const { return m_applicationCache.get(); } - ApplicationCache* mainResourceApplicationCache() const { return m_mainResourceApplicationCache.get(); } - - - // 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; - - // This is the application cache the main resource was loaded from (if any). - RefPtr<ApplicationCache> m_mainResourceApplicationCache; -#endif - }; - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) -#endif // ApplicationCacheHost_h diff --git a/WebCore/loader/appcache/ApplicationCacheResource.cpp b/WebCore/loader/appcache/ApplicationCacheResource.cpp deleted file mode 100644 index 03c5c83..0000000 --- a/WebCore/loader/appcache/ApplicationCacheResource.cpp +++ /dev/null @@ -1,90 +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) - , m_estimatedSizeInStorage(0) -{ -} - -void ApplicationCacheResource::addType(unsigned type) -{ - // Caller should take care of storing the new type in database. - m_type |= type; -} - -int64_t ApplicationCacheResource::estimatedSizeInStorage() -{ - if (m_estimatedSizeInStorage) - return m_estimatedSizeInStorage; - - if (data()) - m_estimatedSizeInStorage = data()->size(); - - HTTPHeaderMap::const_iterator end = response().httpHeaderFields().end(); - for (HTTPHeaderMap::const_iterator it = response().httpHeaderFields().begin(); it != end; ++it) - m_estimatedSizeInStorage += (it->first.length() + it->second.length() + 2) * sizeof(UChar); - - m_estimatedSizeInStorage += url().string().length() * sizeof(UChar); - m_estimatedSizeInStorage += sizeof(int); // response().m_httpStatusCode - m_estimatedSizeInStorage += response().url().string().length() * sizeof(UChar); - m_estimatedSizeInStorage += sizeof(unsigned); // dataId - m_estimatedSizeInStorage += response().mimeType().length() * sizeof(UChar); - m_estimatedSizeInStorage += response().textEncodingName().length() * sizeof(UChar); - - return m_estimatedSizeInStorage; -} - -#ifndef NDEBUG -void ApplicationCacheResource::dumpType(unsigned type) -{ - if (type & Master) - printf("master "); - if (type & Manifest) - printf("manifest "); - if (type & Explicit) - printf("explicit "); - if (type & Foreign) - printf("foreign "); - if (type & Fallback) - printf("fallback "); - - 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 2ca7846..0000000 --- a/WebCore/loader/appcache/ApplicationCacheResource.h +++ /dev/null @@ -1,75 +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 { - Master = 1 << 0, - Manifest = 1 << 1, - Explicit = 1 << 2, - Foreign = 1 << 3, - Fallback = 1 << 4 - }; - - static PassRefPtr<ApplicationCacheResource> create(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer = SharedBuffer::create()) - { - ASSERT(!url.hasFragmentIdentifier()); - 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; } - int64_t estimatedSizeInStorage(); - -#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; - int64_t m_estimatedSizeInStorage; -}; - -} // 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 7b20775..0000000 --- a/WebCore/loader/appcache/ApplicationCacheStorage.cpp +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 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 "ApplicationCacheHost.h" -#include "ApplicationCacheResource.h" -#include "FileSystem.h" -#include "KURL.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" -#include "SecurityOrigin.h" -#include <wtf/text/CString.h> -#include <wtf/StdLibExtras.h> -#include <wtf/StringExtras.h> - -using namespace std; - -namespace WebCore { - -template <class T> -class StorageIDJournal { -public: - ~StorageIDJournal() - { - size_t size = m_records.size(); - for (size_t i = 0; i < size; ++i) - m_records[i].restore(); - } - - void add(T* resource, unsigned storageID) - { - m_records.append(Record(resource, storageID)); - } - - void commit() - { - m_records.clear(); - } - -private: - class Record { - public: - Record() : m_resource(0), m_storageID(0) { } - Record(T* resource, unsigned storageID) : m_resource(resource), m_storageID(storageID) { } - - void restore() - { - m_resource->setStorageID(m_storageID); - } - - private: - T* m_resource; - unsigned m_storageID; - }; - - Vector<Record> m_records; -}; - -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 = static_cast<unsigned>(statement.getColumnInt64(2)); - - RefPtr<ApplicationCache> cache = loadCache(newestCacheStorageID); - if (!cache) - return 0; - - ApplicationCacheGroup* group = new ApplicationCacheGroup(manifestURL); - - group->setStorageID(static_cast<unsigned>(statement.getColumnInt64(0))); - group->setNewestCache(cache.release()); - - return group; -} - -ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const KURL& manifestURL) -{ - ASSERT(!manifestURL.hasFragmentIdentifier()); - - 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; - - while (statement.step() == SQLResultRow) - m_cacheHostSet.add(static_cast<unsigned>(statement.getColumnInt64(0))); -} - -ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url) -{ - ASSERT(!url.hasFragmentIdentifier()); - - 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; - - ASSERT(!group->isObsolete()); - - if (!protocolHostAndPortAreEqual(url, group->manifestURL())) - continue; - - if (ApplicationCache* cache = group->newestCache()) { - ApplicationCacheResource* resource = cache->resourceForURL(url); - if (!resource) - continue; - if (resource->type() & ApplicationCacheResource::Foreign) - continue; - 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(ParsedURLString, statement.getColumnText(1)); - - if (m_cachesInMemory.contains(manifestURL)) - continue; - - 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 = static_cast<unsigned>(statement.getColumnInt64(2)); - RefPtr<ApplicationCache> cache = loadCache(newestCacheID); - if (!cache) - continue; - - ApplicationCacheResource* resource = cache->resourceForURL(url); - if (!resource) - continue; - if (resource->type() & ApplicationCacheResource::Foreign) - continue; - - ApplicationCacheGroup* group = new ApplicationCacheGroup(manifestURL); - - group->setStorageID(static_cast<unsigned>(statement.getColumnInt64(0))); - group->setNewestCache(cache.release()); - - 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; -} - -ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const KURL& url) -{ - ASSERT(!url.hasFragmentIdentifier()); - - // Check if an appropriate 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; - - ASSERT(!group->isObsolete()); - - if (ApplicationCache* cache = group->newestCache()) { - KURL fallbackURL; - if (!cache->urlMatchesFallbackNamespace(url, &fallbackURL)) - continue; - if (cache->resourceForURL(fallbackURL)->type() & ApplicationCacheResource::Foreign) - continue; - 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(ParsedURLString, statement.getColumnText(1)); - - if (m_cachesInMemory.contains(manifestURL)) - continue; - - // Fallback namespaces always have the same origin as manifest URL, so we can avoid loading caches that cannot match. - if (!protocolHostAndPortAreEqual(url, manifestURL)) - continue; - - // We found a cache group that matches. Now check if the newest cache has a resource with - // a matching fallback namespace. - unsigned newestCacheID = static_cast<unsigned>(statement.getColumnInt64(2)); - RefPtr<ApplicationCache> cache = loadCache(newestCacheID); - - KURL fallbackURL; - if (!cache->urlMatchesFallbackNamespace(url, &fallbackURL)) - continue; - if (cache->resourceForURL(fallbackURL)->type() & ApplicationCacheResource::Foreign) - continue; - - ApplicationCacheGroup* group = new ApplicationCacheGroup(manifestURL); - - group->setStorageID(static_cast<unsigned>(statement.getColumnInt64(0))); - group->setNewestCache(cache.release()); - - 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) -{ - if (group->isObsolete()) { - ASSERT(!group->storageID()); - ASSERT(m_cachesInMemory.get(group->manifestURL()) != group); - return; - } - - ASSERT(m_cachesInMemory.get(group->manifestURL()) == group); - - m_cachesInMemory.remove(group->manifestURL()); - - // If the cache group is half-created, we don't want it in the saved set (as it is not stored in database). - if (!group->storageID()) - m_cacheHostSet.remove(urlHostHash(group->manifestURL())); -} - -void ApplicationCacheStorage::cacheGroupMadeObsolete(ApplicationCacheGroup* group) -{ - ASSERT(m_cachesInMemory.get(group->manifestURL()) == group); - ASSERT(m_cacheHostSet.contains(urlHostHash(group->manifestURL()))); - - if (ApplicationCache* newestCache = group->newestCache()) - remove(newestCache); - - m_cachesInMemory.remove(group->manifestURL()); - m_cacheHostSet.remove(urlHostHash(group->manifestURL())); -} - -void ApplicationCacheStorage::setCacheDirectory(const String& cacheDirectory) -{ - ASSERT(m_cacheDirectory.isNull()); - ASSERT(!cacheDirectory.isNull()); - - m_cacheDirectory = cacheDirectory; -} - -const String& ApplicationCacheStorage::cacheDirectory() const -{ - return m_cacheDirectory; -} - -void ApplicationCacheStorage::setMaximumSize(int64_t size) -{ - m_maximumSize = size; -} - -int64_t ApplicationCacheStorage::maximumSize() const -{ - return m_maximumSize; -} - -bool ApplicationCacheStorage::isMaximumSizeReached() const -{ - return m_isMaximumSizeReached; -} - -int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave) -{ - int64_t spaceNeeded = 0; - long long fileSize = 0; - if (!getFileSize(m_cacheFile, fileSize)) - return 0; - - int64_t currentSize = fileSize; - - // Determine the amount of free space we have available. - int64_t totalAvailableSize = 0; - if (m_maximumSize < currentSize) { - // The max size is smaller than the actual size of the app cache file. - // This can happen if the client previously imposed a larger max size - // value and the app cache file has already grown beyond the current - // max size value. - // The amount of free space is just the amount of free space inside - // the database file. Note that this is always 0 if SQLite is compiled - // with AUTO_VACUUM = 1. - totalAvailableSize = m_database.freeSpaceSize(); - } else { - // The max size is the same or larger than the current size. - // The amount of free space available is the amount of free space - // inside the database file plus the amount we can grow until we hit - // the max size. - totalAvailableSize = (m_maximumSize - currentSize) + m_database.freeSpaceSize(); - } - - // The space needed to be freed in order to accommodate the failed cache is - // the size of the failed cache minus any already available free space. - spaceNeeded = cacheToSave - totalAvailableSize; - // The space needed value must be positive (or else the total already - // available free space would be larger than the size of the failed cache and - // saving of the cache should have never failed). - ASSERT(spaceNeeded); - return spaceNeeded; -} - -void ApplicationCacheStorage::setDefaultOriginQuota(int64_t quota) -{ - m_defaultOriginQuota = quota; -} - -bool ApplicationCacheStorage::quotaForOrigin(const SecurityOrigin* origin, int64_t& quota) -{ - // If an Origin record doesn't exist, then the COUNT will be 0 and quota will be 0. - // Using the count to determine if a record existed or not is a safe way to determine - // if a quota of 0 is real, from the record, or from null. - SQLiteStatement statement(m_database, "SELECT COUNT(quota), quota FROM Origins WHERE origin=?"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindText(1, origin->databaseIdentifier()); - int result = statement.step(); - - // Return the quota, or if it was null the default. - if (result == SQLResultRow) { - bool wasNoRecord = statement.getColumnInt64(0) == 0; - quota = wasNoRecord ? m_defaultOriginQuota : statement.getColumnInt64(1); - return true; - } - - LOG_ERROR("Could not get the quota of an origin, error \"%s\"", m_database.lastErrorMsg()); - return false; -} - -bool ApplicationCacheStorage::usageForOrigin(const SecurityOrigin* origin, int64_t& usage) -{ - // If an Origins record doesn't exist, then the SUM will be null, - // which will become 0, as expected, when converting to a number. - SQLiteStatement statement(m_database, "SELECT SUM(Caches.size)" - " FROM CacheGroups" - " INNER JOIN Origins ON CacheGroups.origin = Origins.origin" - " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup" - " WHERE Origins.origin=?"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindText(1, origin->databaseIdentifier()); - int result = statement.step(); - - if (result == SQLResultRow) { - usage = statement.getColumnInt64(0); - return true; - } - - LOG_ERROR("Could not get the quota of an origin, error \"%s\"", m_database.lastErrorMsg()); - return false; -} - -bool ApplicationCacheStorage::remainingSizeForOriginExcludingCache(const SecurityOrigin* origin, ApplicationCache* cache, int64_t& remainingSize) -{ - openDatabase(false); - if (!m_database.isOpen()) - return false; - - // Remaining size = total origin quota - size of all caches with origin excluding the provided cache. - // Keep track of the number of caches so we can tell if the result was a calculation or not. - const char* query; - int64_t excludingCacheIdentifier = cache ? cache->storageID() : 0; - if (excludingCacheIdentifier != 0) { - query = "SELECT COUNT(Caches.size), Origins.quota - SUM(Caches.size)" - " FROM CacheGroups" - " INNER JOIN Origins ON CacheGroups.origin = Origins.origin" - " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup" - " WHERE Origins.origin=?" - " AND Caches.id!=?"; - } else { - query = "SELECT COUNT(Caches.size), Origins.quota - SUM(Caches.size)" - " FROM CacheGroups" - " INNER JOIN Origins ON CacheGroups.origin = Origins.origin" - " INNER JOIN Caches ON CacheGroups.id = Caches.cacheGroup" - " WHERE Origins.origin=?"; - } - - SQLiteStatement statement(m_database, query); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindText(1, origin->databaseIdentifier()); - if (excludingCacheIdentifier != 0) - statement.bindInt64(2, excludingCacheIdentifier); - int result = statement.step(); - - // If the count was 0 that then we have to query the origin table directly - // for its quota. Otherwise we can use the calculated value. - if (result == SQLResultRow) { - int64_t numberOfCaches = statement.getColumnInt64(0); - if (numberOfCaches == 0) - quotaForOrigin(origin, remainingSize); - else - remainingSize = statement.getColumnInt64(1); - return true; - } - - LOG_ERROR("Could not get the remaining size of an origin's quota, error \"%s\"", m_database.lastErrorMsg()); - return false; -} - -bool ApplicationCacheStorage::storeUpdatedQuotaForOrigin(const SecurityOrigin* origin, int64_t quota) -{ - openDatabase(true); - if (!m_database.isOpen()) - return false; - - if (!ensureOriginRecord(origin)) - return false; - - SQLiteStatement updateStatement(m_database, "UPDATE Origins SET quota=? WHERE origin=?"); - if (updateStatement.prepare() != SQLResultOk) - return false; - - updateStatement.bindInt64(1, quota); - updateStatement.bindText(2, origin->databaseIdentifier()); - - return executeStatement(updateStatement); -} - -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; -} - -// Update the schemaVersion when the schema of any the Application Cache -// SQLite tables changes. This allows the database to be rebuilt when -// a new, incompatible change has been introduced to the database schema. -static const int schemaVersion = 6; - -void ApplicationCacheStorage::verifySchemaVersion() -{ - int version = SQLiteStatement(m_database, "PRAGMA user_version").getColumnInt(0); - if (version == schemaVersion) - return; - - m_database.clearAllTables(); - - // Update user version. - SQLiteTransaction setDatabaseVersion(m_database); - setDatabaseVersion.begin(); - - char userVersionSQL[32]; - int unusedNumBytes = snprintf(userVersionSQL, sizeof(userVersionSQL), "PRAGMA user_version=%d", schemaVersion); - ASSERT_UNUSED(unusedNumBytes, static_cast<int>(sizeof(userVersionSQL)) >= unusedNumBytes); - - SQLiteStatement statement(m_database, userVersionSQL); - if (statement.prepare() != SQLResultOk) - return; - - executeStatement(statement); - setDatabaseVersion.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; - - m_cacheFile = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db"); - if (!createIfDoesNotExist && !fileExists(m_cacheFile)) - return; - - makeAllDirectories(m_cacheDirectory); - m_database.open(m_cacheFile); - - 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, origin TEXT)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER, size 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 CacheAllowsAllNetworkRequests (wildcard INTEGER 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)"); - executeSQLCommand("CREATE TABLE IF NOT EXISTS Origins (origin TEXT UNIQUE ON CONFLICT IGNORE, quota INTEGER NOT NULL ON CONFLICT FAIL)"); - - // 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 CacheAllowsAllNetworkRequests WHERE cache = OLD.id;" - " DELETE FROM FallbackURLs WHERE cache = OLD.id;" - " END"); - - // When a cache entry is deleted, its resource should also be deleted. - executeSQLCommand("CREATE TRIGGER IF NOT EXISTS CacheEntryDeleted AFTER DELETE ON CacheEntries" - " FOR EACH ROW BEGIN" - " DELETE FROM CacheResources WHERE id = OLD.resource;" - " 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, GroupStorageIDJournal* journal) -{ - ASSERT(group->storageID() == 0); - ASSERT(journal); - - SQLiteStatement statement(m_database, "INSERT INTO CacheGroups (manifestHostHash, manifestURL, origin) VALUES (?, ?, ?)"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindInt64(1, urlHostHash(group->manifestURL())); - statement.bindText(2, group->manifestURL()); - statement.bindText(3, group->origin()->databaseIdentifier()); - - if (!executeStatement(statement)) - return false; - - unsigned groupStorageID = static_cast<unsigned>(m_database.lastInsertRowID()); - - if (!ensureOriginRecord(group->origin())) - return false; - - group->setStorageID(groupStorageID); - journal->add(group, 0); - return true; -} - -bool ApplicationCacheStorage::store(ApplicationCache* cache, ResourceStorageIDJournal* storageIDJournal) -{ - ASSERT(cache->storageID() == 0); - ASSERT(cache->group()->storageID() != 0); - ASSERT(storageIDJournal); - - SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup, size) VALUES (?, ?)"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindInt64(1, cache->group()->storageID()); - statement.bindInt64(2, cache->estimatedSizeInStorage()); - - if (!executeStatement(statement)) - return false; - - unsigned cacheStorageID = static_cast<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) { - unsigned oldStorageID = it->second->storageID(); - if (!store(it->second.get(), cacheStorageID)) - return false; - - // Storing the resource succeeded. Log its old storageID in case - // it needs to be restored later. - storageIDJournal->add(it->second.get(), oldStorageID); - } - } - - // Store the online whitelist - const Vector<KURL>& onlineWhitelist = cache->onlineWhitelist(); - { - size_t whitelistSize = onlineWhitelist.size(); - for (size_t i = 0; i < whitelistSize; ++i) { - SQLiteStatement statement(m_database, "INSERT INTO CacheWhitelistURLs (url, cache) VALUES (?, ?)"); - statement.prepare(); - - statement.bindText(1, onlineWhitelist[i]); - statement.bindInt64(2, cacheStorageID); - - if (!executeStatement(statement)) - return false; - } - } - - // Store online whitelist wildcard flag. - { - SQLiteStatement statement(m_database, "INSERT INTO CacheAllowsAllNetworkRequests (wildcard, cache) VALUES (?, ?)"); - statement.prepare(); - - statement.bindInt64(1, cache->allowsAllNetworkRequests()); - statement.bindInt64(2, cacheStorageID); - - if (!executeStatement(statement)) - return false; - } - - // Store fallback URLs. - const FallbackURLVector& fallbackURLs = cache->fallbackURLs(); - { - size_t fallbackCount = fallbackURLs.size(); - for (size_t i = 0; i < fallbackCount; ++i) { - SQLiteStatement statement(m_database, "INSERT INTO FallbackURLs (namespace, fallbackURL, cache) VALUES (?, ?, ?)"); - statement.prepare(); - - statement.bindText(1, fallbackURLs[i].first); - statement.bindText(2, fallbackURLs[i].second); - statement.bindInt64(3, 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); - - // openDatabase(true) could still fail, for example when cacheStorage is full or no longer available. - if (!m_database.isOpen()) - return false; - - // 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 = static_cast<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; - - // The same ApplicationCacheResource are used in ApplicationCacheResource::size() - // to calculate the approximate size of an ApplicationCacheResource object. If - // you change the code below, please also change ApplicationCacheResource::size(). - 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 = static_cast<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; -} - -bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resource, ApplicationCache* cache) -{ - ASSERT_UNUSED(cache, cache->storageID()); - ASSERT(resource->storageID()); - - // First, insert the data - SQLiteStatement entryStatement(m_database, "UPDATE CacheEntries SET type=? WHERE resource=?"); - if (entryStatement.prepare() != SQLResultOk) - return false; - - entryStatement.bindInt64(1, resource->type()); - entryStatement.bindInt64(2, resource->storageID()); - - return executeStatement(entryStatement); -} - -bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache) -{ - ASSERT(cache->storageID()); - - openDatabase(true); - - if (!m_database.isOpen()) - return false; - - m_isMaximumSizeReached = false; - m_database.setMaximumSize(m_maximumSize); - - SQLiteTransaction storeResourceTransaction(m_database); - storeResourceTransaction.begin(); - - if (!store(resource, cache->storageID())) { - checkForMaxSizeReached(); - return false; - } - - // A resource was added to the cache. Update the total data size for the cache. - SQLiteStatement sizeUpdateStatement(m_database, "UPDATE Caches SET size=size+? WHERE id=?"); - if (sizeUpdateStatement.prepare() != SQLResultOk) - return false; - - sizeUpdateStatement.bindInt64(1, resource->estimatedSizeInStorage()); - sizeUpdateStatement.bindInt64(2, cache->storageID()); - - if (!executeStatement(sizeUpdateStatement)) - return false; - - storeResourceTransaction.commit(); - return true; -} - -bool ApplicationCacheStorage::ensureOriginRecord(const SecurityOrigin* origin) -{ - SQLiteStatement insertOriginStatement(m_database, "INSERT INTO Origins (origin, quota) VALUES (?, ?)"); - if (insertOriginStatement.prepare() != SQLResultOk) - return false; - - insertOriginStatement.bindText(1, origin->databaseIdentifier()); - insertOriginStatement.bindInt64(2, m_defaultOriginQuota); - if (!executeStatement(insertOriginStatement)) - return false; - - return true; -} - -bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup* group, ApplicationCache* oldCache, FailureReason& failureReason) -{ - openDatabase(true); - - if (!m_database.isOpen()) - return false; - - m_isMaximumSizeReached = false; - m_database.setMaximumSize(m_maximumSize); - - SQLiteTransaction storeCacheTransaction(m_database); - - storeCacheTransaction.begin(); - - // Check if this would reach the per-origin quota. - int64_t remainingSpaceInOrigin; - if (remainingSizeForOriginExcludingCache(group->origin(), oldCache, remainingSpaceInOrigin)) { - if (remainingSpaceInOrigin < group->newestCache()->estimatedSizeInStorage()) { - failureReason = OriginQuotaReached; - return false; - } - } - - GroupStorageIDJournal groupStorageIDJournal; - if (!group->storageID()) { - // Store the group - if (!store(group, &groupStorageIDJournal)) { - checkForMaxSizeReached(); - failureReason = isMaximumSizeReached() ? TotalQuotaReached : DiskOrOperationFailure; - return false; - } - } - - ASSERT(group->newestCache()); - ASSERT(!group->isObsolete()); - ASSERT(!group->newestCache()->storageID()); - - // Log the storageID changes to the in-memory resource objects. The journal - // object will roll them back automatically in case a database operation - // fails and this method returns early. - ResourceStorageIDJournal resourceStorageIDJournal; - - // Store the newest cache - if (!store(group->newestCache(), &resourceStorageIDJournal)) { - checkForMaxSizeReached(); - failureReason = isMaximumSizeReached() ? TotalQuotaReached : DiskOrOperationFailure; - return false; - } - - // Update the newest cache in the group. - - SQLiteStatement statement(m_database, "UPDATE CacheGroups SET newestCache=? WHERE id=?"); - if (statement.prepare() != SQLResultOk) { - failureReason = DiskOrOperationFailure; - return false; - } - - statement.bindInt64(1, group->newestCache()->storageID()); - statement.bindInt64(2, group->storageID()); - - if (!executeStatement(statement)) { - failureReason = DiskOrOperationFailure; - return false; - } - - groupStorageIDJournal.commit(); - resourceStorageIDJournal.commit(); - storeCacheTransaction.commit(); - return true; -} - -bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup* group) -{ - // Ignore the reason for failing, just attempt the store. - FailureReason ignoredFailureReason; - return storeNewestCache(group, 0, ignoredFailureReason); -} - -static inline void parseHeader(const UChar* header, size_t headerLength, ResourceResponse& response) -{ - size_t pos = find(header, headerLength, ':'); - ASSERT(pos != notFound); - - AtomicString headerName = AtomicString(header, pos); - String headerValue = String(header + pos + 1, headerLength - pos - 1); - - response.setHTTPHeaderField(headerName, headerValue); -} - -static inline void parseHeaders(const String& headers, ResourceResponse& response) -{ - unsigned startPos = 0; - size_t endPos; - while ((endPos = headers.find('\n', startPos)) != notFound) { - ASSERT(startPos != endPos); - - parseHeader(headers.characters() + startPos, endPos - startPos, response); - - startPos = endPos + 1; - } - - if (startPos != 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(ParsedURLString, cacheStatement.getColumnText(0)); - - unsigned type = static_cast<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); - - Vector<KURL> whitelist; - while ((result = whitelistStatement.step()) == SQLResultRow) - whitelist.append(KURL(ParsedURLString, whitelistStatement.getColumnText(0))); - - if (result != SQLResultDone) - LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg()); - - cache->setOnlineWhitelist(whitelist); - - // Load online whitelist wildcard flag. - SQLiteStatement whitelistWildcardStatement(m_database, "SELECT wildcard FROM CacheAllowsAllNetworkRequests WHERE cache=?"); - if (whitelistWildcardStatement.prepare() != SQLResultOk) - return 0; - whitelistWildcardStatement.bindInt64(1, storageID); - - result = whitelistWildcardStatement.step(); - if (result != SQLResultRow) - LOG_ERROR("Could not load cache online whitelist wildcard flag, error \"%s\"", m_database.lastErrorMsg()); - - cache->setAllowsAllNetworkRequests(whitelistWildcardStatement.getColumnInt64(0)); - - if (whitelistWildcardStatement.step() != SQLResultDone) - LOG_ERROR("Too many rows for online whitelist wildcard flag"); - - // Load fallback URLs. - SQLiteStatement fallbackStatement(m_database, "SELECT namespace, fallbackURL FROM FallbackURLs WHERE cache=?"); - if (fallbackStatement.prepare() != SQLResultOk) - return 0; - fallbackStatement.bindInt64(1, storageID); - - FallbackURLVector fallbackURLs; - while ((result = fallbackStatement.step()) == SQLResultRow) - fallbackURLs.append(make_pair(KURL(ParsedURLString, fallbackStatement.getColumnText(0)), KURL(ParsedURLString, fallbackStatement.getColumnText(1)))); - - if (result != SQLResultDone) - LOG_ERROR("Could not load fallback URLs, error \"%s\"", m_database.lastErrorMsg()); - - cache->setFallbackURLs(fallbackURLs); - - cache->setStorageID(storageID); - - return cache.release(); -} - -void ApplicationCacheStorage::remove(ApplicationCache* cache) -{ - if (!cache->storageID()) - return; - - openDatabase(false); - if (!m_database.isOpen()) - return; - - ASSERT(cache->group()); - ASSERT(cache->group()->storageID()); - - // All associated data will be deleted by database triggers. - SQLiteStatement statement(m_database, "DELETE FROM Caches WHERE id=?"); - if (statement.prepare() != SQLResultOk) - return; - - statement.bindInt64(1, cache->storageID()); - executeStatement(statement); - - cache->clearStorageID(); - - if (cache->group()->newestCache() == cache) { - // Currently, there are no triggers on the cache group, which is why the cache had to be removed separately above. - SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?"); - if (groupStatement.prepare() != SQLResultOk) - return; - - groupStatement.bindInt64(1, cache->group()->storageID()); - executeStatement(groupStatement); - - cache->group()->clearStorageID(); - } -} - -void ApplicationCacheStorage::empty() -{ - openDatabase(false); - - if (!m_database.isOpen()) - return; - - // Clear cache groups, caches, cache resources, and origins. - executeSQLCommand("DELETE FROM CacheGroups"); - executeSQLCommand("DELETE FROM Caches"); - executeSQLCommand("DELETE FROM Origins"); - - // 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, ApplicationCacheHost* cacheHost) -{ - ApplicationCache* cache = cacheHost->applicationCache(); - if (!cache) - return true; - - // Create a new cache. - RefPtr<ApplicationCache> cacheCopy = ApplicationCache::create(); - - cacheCopy->setOnlineWhitelist(cache->onlineWhitelist()); - cacheCopy->setFallbackURLs(cache->fallbackURLs()); - - // 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(adoptPtr(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()); -} - -bool ApplicationCacheStorage::manifestURLs(Vector<KURL>* urls) -{ - ASSERT(urls); - openDatabase(false); - if (!m_database.isOpen()) - return false; - - SQLiteStatement selectURLs(m_database, "SELECT manifestURL FROM CacheGroups"); - - if (selectURLs.prepare() != SQLResultOk) - return false; - - while (selectURLs.step() == SQLResultRow) - urls->append(KURL(ParsedURLString, selectURLs.getColumnText(0))); - - return true; -} - -bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t* size) -{ - ASSERT(size); - openDatabase(false); - if (!m_database.isOpen()) - return false; - - SQLiteStatement statement(m_database, "SELECT sum(Caches.size) FROM Caches INNER JOIN CacheGroups ON Caches.cacheGroup=CacheGroups.id WHERE CacheGroups.manifestURL=?"); - if (statement.prepare() != SQLResultOk) - return false; - - statement.bindText(1, manifestURL); - - int result = statement.step(); - if (result == SQLResultDone) - return false; - - if (result != SQLResultRow) { - LOG_ERROR("Could not get the size of the cache group, error \"%s\"", m_database.lastErrorMsg()); - return false; - } - - *size = statement.getColumnInt64(0); - return true; -} - -bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL) -{ - SQLiteTransaction deleteTransaction(m_database); - // Check to see if the group is in memory. - ApplicationCacheGroup* group = m_cachesInMemory.get(manifestURL); - if (group) - cacheGroupMadeObsolete(group); - else { - // The cache group is not in memory, so remove it from the disk. - openDatabase(false); - if (!m_database.isOpen()) - return false; - - SQLiteStatement idStatement(m_database, "SELECT id FROM CacheGroups WHERE manifestURL=?"); - if (idStatement.prepare() != SQLResultOk) - return false; - - idStatement.bindText(1, manifestURL); - - int result = idStatement.step(); - if (result == SQLResultDone) - return false; - - if (result != SQLResultRow) { - LOG_ERROR("Could not load cache group id, error \"%s\"", m_database.lastErrorMsg()); - return false; - } - - int64_t groupId = idStatement.getColumnInt64(0); - - SQLiteStatement cacheStatement(m_database, "DELETE FROM Caches WHERE cacheGroup=?"); - if (cacheStatement.prepare() != SQLResultOk) - return false; - - SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?"); - if (groupStatement.prepare() != SQLResultOk) - return false; - - cacheStatement.bindInt64(1, groupId); - executeStatement(cacheStatement); - groupStatement.bindInt64(1, groupId); - executeStatement(groupStatement); - } - - deleteTransaction.commit(); - return true; -} - -void ApplicationCacheStorage::vacuumDatabaseFile() -{ - openDatabase(false); - if (!m_database.isOpen()) - return; - - m_database.runVacuumCommand(); -} - -void ApplicationCacheStorage::checkForMaxSizeReached() -{ - if (m_database.lastError() == SQLResultFull) - m_isMaximumSizeReached = true; -} - -ApplicationCacheStorage::ApplicationCacheStorage() - : m_maximumSize(ApplicationCacheStorage::noQuota()) - , m_isMaximumSizeReached(false) - , m_defaultOriginQuota(ApplicationCacheStorage::noQuota()) -{ -} - -ApplicationCacheStorage& cacheStorage() -{ - DEFINE_STATIC_LOCAL(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 7db34e6..0000000 --- a/WebCore/loader/appcache/ApplicationCacheStorage.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2008, 2010 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 <wtf/HashCountedSet.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class ApplicationCache; -class ApplicationCacheGroup; -class ApplicationCacheHost; -class ApplicationCacheResource; -class KURL; -template <class T> -class StorageIDJournal; -class SecurityOrigin; - -class ApplicationCacheStorage : public Noncopyable { -public: - enum FailureReason { - OriginQuotaReached, - TotalQuotaReached, - DiskOrOperationFailure - }; - - void setCacheDirectory(const String&); - const String& cacheDirectory() const; - - void setMaximumSize(int64_t size); - int64_t maximumSize() const; - bool isMaximumSizeReached() const; - int64_t spaceNeeded(int64_t cacheToSave); - - int64_t defaultOriginQuota() const { return m_defaultOriginQuota; } - void setDefaultOriginQuota(int64_t quota); - bool usageForOrigin(const SecurityOrigin*, int64_t& usage); - bool quotaForOrigin(const SecurityOrigin*, int64_t& quota); - bool remainingSizeForOriginExcludingCache(const SecurityOrigin*, ApplicationCache*, int64_t& remainingSize); - bool storeUpdatedQuotaForOrigin(const SecurityOrigin*, int64_t quota); - - ApplicationCacheGroup* cacheGroupForURL(const KURL&); // Cache to load a main resource from. - ApplicationCacheGroup* fallbackCacheGroupForURL(const KURL&); // Cache that has a fallback entry to load a main resource from if normal loading fails. - - ApplicationCacheGroup* findOrCreateCacheGroup(const KURL& manifestURL); - void cacheGroupDestroyed(ApplicationCacheGroup*); - void cacheGroupMadeObsolete(ApplicationCacheGroup*); - - bool storeNewestCache(ApplicationCacheGroup*, ApplicationCache* oldCache, FailureReason& failureReason); - bool storeNewestCache(ApplicationCacheGroup*); // Updates the cache group, but doesn't remove old cache. - bool store(ApplicationCacheResource*, ApplicationCache*); - bool storeUpdatedType(ApplicationCacheResource*, ApplicationCache*); - - // Removes the group if the cache to be removed is the newest one (so, storeNewestCache() needs to be called beforehand when updating). - void remove(ApplicationCache*); - - void empty(); - - static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost*); - - bool manifestURLs(Vector<KURL>* urls); - bool cacheGroupSize(const String& manifestURL, int64_t* size); - bool deleteCacheGroup(const String& manifestURL); - void vacuumDatabaseFile(); - - static int64_t unknownQuota() { return -1; } - static int64_t noQuota() { return std::numeric_limits<int64_t>::max(); } -private: - ApplicationCacheStorage(); - PassRefPtr<ApplicationCache> loadCache(unsigned storageID); - ApplicationCacheGroup* loadCacheGroup(const KURL& manifestURL); - - typedef StorageIDJournal<ApplicationCacheResource> ResourceStorageIDJournal; - typedef StorageIDJournal<ApplicationCacheGroup> GroupStorageIDJournal; - - bool store(ApplicationCacheGroup*, GroupStorageIDJournal*); - bool store(ApplicationCache*, ResourceStorageIDJournal*); - bool store(ApplicationCacheResource*, unsigned cacheStorageID); - - bool ensureOriginRecord(const SecurityOrigin*); - - void loadManifestHostHashes(); - - void verifySchemaVersion(); - - void openDatabase(bool createIfDoesNotExist); - - bool executeStatement(SQLiteStatement&); - bool executeSQLCommand(const String&); - - void checkForMaxSizeReached(); - - String m_cacheDirectory; - String m_cacheFile; - - int64_t m_maximumSize; - bool m_isMaximumSizeReached; - - int64_t m_defaultOriginQuota; - - SQLiteDatabase m_database; - - // In order to quickly determine if a given resource exists in an application cache, - // we keep a hash set of the hosts of the manifest URLs of all non-obsolete cache groups. - HashCountedSet<unsigned, AlreadyHashed> m_cacheHostSet; - - typedef HashMap<String, ApplicationCacheGroup*> CacheGroupMap; - CacheGroupMap m_cachesInMemory; // Excludes obsolete cache groups. - - friend ApplicationCacheStorage& cacheStorage(); -}; - -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 b9297b1..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "ApplicationCacheHost.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) -{ - ApplicationCacheHost* cacheHost = applicationCacheHost(); - if (cacheHost) - cacheHost->setDOMApplicationCache(this); -} - -void DOMApplicationCache::disconnectFrame() -{ - ApplicationCacheHost* cacheHost = applicationCacheHost(); - if (cacheHost) - cacheHost->setDOMApplicationCache(0); - m_frame = 0; -} - -ApplicationCacheHost* DOMApplicationCache::applicationCacheHost() const -{ - if (!m_frame || !m_frame->loader()->documentLoader()) - return 0; - return m_frame->loader()->documentLoader()->applicationCacheHost(); -} - -unsigned short DOMApplicationCache::status() const -{ - ApplicationCacheHost* cacheHost = applicationCacheHost(); - if (!cacheHost) - return ApplicationCacheHost::UNCACHED; - return cacheHost->status(); -} - -void DOMApplicationCache::update(ExceptionCode& ec) -{ - ApplicationCacheHost* cacheHost = applicationCacheHost(); - if (!cacheHost || !cacheHost->update()) - ec = INVALID_STATE_ERR; -} - -void DOMApplicationCache::swapCache(ExceptionCode& ec) -{ - ApplicationCacheHost* cacheHost = applicationCacheHost(); - if (!cacheHost || !cacheHost->swapCache()) - ec = INVALID_STATE_ERR; -} - -ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const -{ - if (m_frame) - return m_frame->document(); - return 0; -} - -const AtomicString& DOMApplicationCache::toEventType(ApplicationCacheHost::EventID id) -{ - switch (id) { - case ApplicationCacheHost::CHECKING_EVENT: - return eventNames().checkingEvent; - case ApplicationCacheHost::ERROR_EVENT: - return eventNames().errorEvent; - case ApplicationCacheHost::NOUPDATE_EVENT: - return eventNames().noupdateEvent; - case ApplicationCacheHost::DOWNLOADING_EVENT: - return eventNames().downloadingEvent; - case ApplicationCacheHost::PROGRESS_EVENT: - return eventNames().progressEvent; - case ApplicationCacheHost::UPDATEREADY_EVENT: - return eventNames().updatereadyEvent; - case ApplicationCacheHost::CACHED_EVENT: - return eventNames().cachedEvent; - case ApplicationCacheHost::OBSOLETE_EVENT: - return eventNames().obsoleteEvent; - } - ASSERT_NOT_REACHED(); - return eventNames().errorEvent; -} - -EventTargetData* DOMApplicationCache::eventTargetData() -{ - return &m_eventTargetData; -} - -EventTargetData* DOMApplicationCache::ensureEventTargetData() -{ - return &m_eventTargetData; -} - -} // 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 2a806fa..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "ApplicationCacheHost.h" -#include "EventListener.h" -#include "EventNames.h" -#include "EventTarget.h" -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> -#include <wtf/text/AtomicStringHash.h> - -namespace WebCore { - -class Frame; -class KURL; - -class DOMApplicationCache : public RefCounted<DOMApplicationCache>, public EventTarget { -public: - static PassRefPtr<DOMApplicationCache> create(Frame* frame) { return adoptRef(new DOMApplicationCache(frame)); } - ~DOMApplicationCache() { ASSERT(!m_frame); } - - Frame* frame() const { return m_frame; } - void disconnectFrame(); - - unsigned short status() const; - void update(ExceptionCode&); - void swapCache(ExceptionCode&); - - // EventTarget impl - - using RefCounted<DOMApplicationCache>::ref; - using RefCounted<DOMApplicationCache>::deref; - - // Explicitly named attribute event listener helpers - - DEFINE_ATTRIBUTE_EVENT_LISTENER(checking); - DEFINE_ATTRIBUTE_EVENT_LISTENER(error); - DEFINE_ATTRIBUTE_EVENT_LISTENER(noupdate); - DEFINE_ATTRIBUTE_EVENT_LISTENER(downloading); - DEFINE_ATTRIBUTE_EVENT_LISTENER(progress); - DEFINE_ATTRIBUTE_EVENT_LISTENER(updateready); - DEFINE_ATTRIBUTE_EVENT_LISTENER(cached); - DEFINE_ATTRIBUTE_EVENT_LISTENER(obsolete); - - virtual ScriptExecutionContext* scriptExecutionContext() const; - DOMApplicationCache* toDOMApplicationCache() { return this; } - - static const AtomicString& toEventType(ApplicationCacheHost::EventID id); - -private: - DOMApplicationCache(Frame*); - - virtual void refEventTarget() { ref(); } - virtual void derefEventTarget() { deref(); } - virtual EventTargetData* eventTargetData(); - virtual EventTargetData* ensureEventTargetData(); - - ApplicationCacheHost* applicationCacheHost() const; - - Frame* m_frame; - EventTargetData m_eventTargetData; -}; - -} // 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 9113ffa..0000000 --- a/WebCore/loader/appcache/DOMApplicationCache.idl +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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, - EventTarget, - OmitConstructor, - DontCheckEnums - ] 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; - const unsigned short OBSOLETE = 5; - readonly attribute unsigned short status; - - void update() - raises(DOMException); - void swapCache() - raises(DOMException); - - // events - attribute EventListener onchecking; - attribute EventListener onerror; - attribute EventListener onnoupdate; - attribute EventListener ondownloading; - attribute EventListener onprogress; - attribute EventListener onupdateready; - attribute EventListener oncached; - attribute EventListener onobsolete; - - // EventTarget interface - void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - 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 f58a55d..0000000 --- a/WebCore/loader/appcache/ManifestParser.cpp +++ /dev/null @@ -1,188 +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 "TextResourceDecoder.h" - -using namespace std; - -namespace WebCore { - -enum Mode { Explicit, Fallback, OnlineWhitelist, Unknown }; - -bool parseManifest(const KURL& manifestURL, const char* data, int length, Manifest& manifest) -{ - ASSERT(manifest.explicitURLs.isEmpty()); - ASSERT(manifest.onlineWhitelistedURLs.isEmpty()); - ASSERT(manifest.fallbackURLs.isEmpty()); - manifest.allowAllNetworkRequests = false; - - Mode mode = Explicit; - - RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/cache-manifest", "UTF-8"); - String s = decoder->decode(data, length); - s += decoder->flush(); - - // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?" (the BOM is removed by TextResourceDecoder). - // Example: "CACHE MANIFEST #comment" is a valid signature. - // Example: "CACHE MANIFEST;V2" is not. - if (!s.startsWith("CACHE MANIFEST")) - return false; - - const UChar* end = s.characters() + s.length(); - const UChar* p = s.characters() + 14; // "CACHE MANIFEST" is 14 characters. - - if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') - return false; - - // Skip to the end of the line. - while (p < end && *p != '\r' && *p != '\n') - p++; - - 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 (line.endsWith(":")) - mode = Unknown; - else if (mode == Unknown) - continue; - else if (mode == Explicit || mode == OnlineWhitelist) { - const UChar* p = line.characters(); - const UChar* lineEnd = p + line.length(); - - // Look for whitespace separating the URL from subsequent ignored tokens. - while (p < lineEnd && *p != '\t' && *p != ' ') - p++; - - if (mode == OnlineWhitelist && p - line.characters() == 1 && *line.characters() == '*') { - // Wildcard was found. - manifest.allowAllNetworkRequests = true; - continue; - } - - KURL url(manifestURL, String(line.characters(), p - line.characters())); - - if (!url.isValid()) - continue; - - if (url.hasFragmentIdentifier()) - url.removeFragmentIdentifier(); - - if (!equalIgnoringCase(url.protocol(), manifestURL.protocol())) - continue; - - if (mode == Explicit && manifestURL.protocolIs("https") && !protocolHostAndPortAreEqual(manifestURL, url)) - continue; - - if (mode == Explicit) - manifest.explicitURLs.add(url.string()); - else - manifest.onlineWhitelistedURLs.append(url); - - } 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; - if (namespaceURL.hasFragmentIdentifier()) - namespaceURL.removeFragmentIdentifier(); - - if (!protocolHostAndPortAreEqual(manifestURL, namespaceURL)) - continue; - - // Skip whitespace separating fallback namespace from URL. - while (p < lineEnd && (*p == '\t' || *p == ' ')) - p++; - - // Look for whitespace separating the URL from subsequent ignored tokens. - const UChar* fallbackStart = p; - while (p < lineEnd && *p != '\t' && *p != ' ') - p++; - - KURL fallbackURL(manifestURL, String(fallbackStart, p - fallbackStart)); - if (!fallbackURL.isValid()) - continue; - if (fallbackURL.hasFragmentIdentifier()) - fallbackURL.removeFragmentIdentifier(); - - if (!protocolHostAndPortAreEqual(manifestURL, fallbackURL)) - continue; - - manifest.fallbackURLs.append(make_pair(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 f0369ee..0000000 --- a/WebCore/loader/appcache/ManifestParser.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. - * - * 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 "ApplicationCache.h" - -namespace WebCore { - - class KURL; - - struct Manifest { - Vector<KURL> onlineWhitelistedURLs; - HashSet<String> explicitURLs; - FallbackURLVector fallbackURLs; - bool allowAllNetworkRequests; // Wildcard found in NETWORK section. - }; - - 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 5926690..0000000 --- a/WebCore/loader/archive/ArchiveFactory.cpp +++ /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. - * 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" - -#include "MIMETypeRegistry.h" -#include "PlatformString.h" - -#if PLATFORM(CF) && !PLATFORM(QT) -#include "LegacyWebArchive.h" -#elif PLATFORM(ANDROID) -#include "WebArchiveAndroid.h" -#endif - -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/StdLibExtras.h> - -namespace WebCore { - -typedef PassRefPtr<Archive> RawDataCreationFunction(SharedBuffer*); -typedef HashMap<String, RawDataCreationFunction*, CaseFoldingHash> ArchiveMIMETypesMap; - -// 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 ArchiveMIMETypesMap& archiveMIMETypes() -{ - DEFINE_STATIC_LOCAL(ArchiveMIMETypesMap, mimeTypes, ()); - static bool initialized = false; - - if (initialized) - return mimeTypes; - -#if PLATFORM(CF) && !PLATFORM(QT) - mimeTypes.set("application/x-webarchive", archiveFactoryCreate<LegacyWebArchive>); -#elif PLATFORM(ANDROID) - mimeTypes.set("application/x-webarchive-xml", archiveFactoryCreate<WebArchiveAndroid>); -#endif - - initialized = true; - return mimeTypes; -} - -bool ArchiveFactory::isArchiveMimeType(const String& mimeType) -{ - return !mimeType.isEmpty() && archiveMIMETypes().contains(mimeType); -} - -PassRefPtr<Archive> ArchiveFactory::create(SharedBuffer* data, const String& mimeType) -{ - RawDataCreationFunction* function = mimeType.isEmpty() ? 0 : archiveMIMETypes().get(mimeType); - return function ? function(data) : 0; -} - -void ArchiveFactory::registerKnownArchiveMIMETypes() -{ - HashSet<String>& mimeTypes = MIMETypeRegistry::getSupportedNonImageMIMETypes(); - ArchiveMIMETypesMap::iterator i = archiveMIMETypes().begin(); - ArchiveMIMETypesMap::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 c3b9464..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/Forward.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -class SharedBuffer; - -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 7dedc93..0000000 --- a/WebCore/loader/archive/ArchiveResource.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008, 2010 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 { - -inline ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& response) - : SubstituteResource(url, response, data) - , m_mimeType(mimeType) - , m_textEncoding(textEncoding) - , m_frameName(frameName) - , m_shouldIgnoreWhenUnarchiving(false) -{ -} - -PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& response) -{ - if (!data) - return 0; - if (response.isNull()) { - unsigned dataSize = data->size(); - return adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName, - ResourceResponse(url, mimeType, dataSize, textEncoding, String()))); - } - return adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName, response)); -} - -PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const ResourceResponse& response) -{ - return create(data, url, response.mimeType(), response.textEncodingName(), String(), response); -} - -} diff --git a/WebCore/loader/archive/ArchiveResource.h b/WebCore/loader/archive/ArchiveResource.h deleted file mode 100644 index 97d6e32..0000000 --- a/WebCore/loader/archive/ArchiveResource.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008, 2010 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" - -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, - const ResourceResponse& = 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 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 9d630d1..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 : public 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 ddd564e..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchive.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 "MemoryCache.h" -#include "Document.h" -#include "DocumentLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameTree.h" -#include "HTMLFrameOwnerElement.h" -#include "HTMLNames.h" -#include "IconDatabase.h" -#include "Image.h" -#include "KURLHash.h" -#include "Logging.h" -#include "markup.h" -#include "Node.h" -#include "Range.h" -#include "SelectionController.h" -#include "SharedBuffer.h" -#include <wtf/text/CString.h> -#include <wtf/text/StringConcatenate.h> -#include <wtf/ListHashSet.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"); - -RetainPtr<CFDictionaryRef> LegacyWebArchive::createPropertyListRepresentation(ArchiveResource* resource, MainResourceStatus isMainResource) -{ - if (!resource) { - // The property list representation of a null/empty WebResource has the following 3 objects stored as nil. - // FIXME: 0 is not serializable. Presumably we need to use kCFNull here instead for compatibility. - // FIXME: But why do we need to support a resource of 0? Who relies on that? - 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() || isMainResource) { - 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 (!isMainResource) { - RetainPtr<CFDataRef> resourceResponseData = createPropertyListRepresentation(resource->response()); - if (resourceResponseData) - CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceResponseKey, resourceResponseData.get()); - } - - return propertyList; -} - -RetainPtr<CFDictionaryRef> LegacyWebArchive::createPropertyListRepresentation(Archive* archive) -{ - RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, &kCFTypeDictionaryValueCallBacks)); - - RetainPtr<CFDictionaryRef> mainResourceDict = createPropertyListRepresentation(archive->mainResource(), MainResource); - ASSERT(mainResourceDict); - 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 = createPropertyListRepresentation(subresources[i].get(), Subresource); - 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 = createPropertyListRepresentation(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; -} - -ResourceResponse LegacyWebArchive::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" web archive that we - // can parse well in a cross platform manner If it doesn't exist, we will assume this is an "old" web archive with, - // NSURLResponse objects in it and parse the ResourceResponse as such. - if (!responseDataType) - return createResourceResponseFromMacArchivedData(data); - - // FIXME: Parse the "new" format that the above comment references here. This format doesn't exist yet. - return ResourceResponse(); -} - -PassRefPtr<ArchiveResource> LegacyWebArchive::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::wrapCFData(resourceData), KURL(KURL(), url), mimeType, textEncoding, frameName, response); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create() -{ - return adoptRef(new LegacyWebArchive); -} - -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(); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(SharedBuffer* data) -{ - LOG(Archives, "LegacyWebArchive - Creating from raw data"); - - RefPtr<LegacyWebArchive> archive = create(); - - ASSERT(data); - if (!data) - return 0; - - RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData()); - if (!cfData) - return 0; - - 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 0; - } - - if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) { - LOG(Archives, "LegacyWebArchive - Archive property list is not the expected CFDictionary, aborting invalid WebArchive"); - return 0; - } - - if (!archive->extract(plist.get())) - return 0; - - return archive.release(); -} - -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 = createPropertyListRepresentation(this); - ASSERT(propertyList); - if (!propertyList) { - LOG(Archives, "LegacyWebArchive - Failed to create property list for archive, returning no data"); - return 0; - } - - RetainPtr<CFWriteStreamRef> stream(AdoptCF, CFWriteStreamCreateWithAllocatedBuffers(0, 0)); - - CFWriteStreamOpen(stream.get()); - CFPropertyListWriteToStream(propertyList.get(), stream.get(), kCFPropertyListBinaryFormat_v1_0, 0); - - RetainPtr<CFDataRef> plistData(AdoptCF, static_cast<CFDataRef>(CFWriteStreamCopyProperty(stream.get(), kCFStreamPropertyDataWritten))); - ASSERT(plistData); - - CFWriteStreamClose(stream.get()); - - if (!plistData) { - LOG(Archives, "LegacyWebArchive - Failed to convert property list into raw data, returning no data"); - return 0; - } - - return plistData; -} - -#if !PLATFORM(MAC) - -ResourceResponse LegacyWebArchive::createResourceResponseFromMacArchivedData(CFDataRef responseData) -{ - // FIXME: If is is possible to parse in a serialized NSURLResponse manually, without using - // NSKeyedUnarchiver, manipulating plists directly, then we want to do that here. - // Until then, this can be done on Mac only. - return ResourceResponse(); -} - -RetainPtr<CFDataRef> LegacyWebArchive::createPropertyListRepresentation(const ResourceResponse& response) -{ - // FIXME: Write out the "new" format described in createResourceResponseFromPropertyListData once we invent it. - 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 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, const 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(ParsedURLString, ""); - - PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->uniqueName()); - - Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; - Vector<PassRefPtr<ArchiveResource> > subresources; - HashSet<KURL> uniqueSubresources; - - size_t nodesSize = nodes.size(); - for (size_t i = 0; i < nodesSize; ++i) { - Node* node = nodes[i]; - Frame* childFrame; - if ((node->hasTagName(HTMLNames::frameTag) || node->hasTagName(HTMLNames::iframeTag) || node->hasTagName(HTMLNames::objectTag)) && - (childFrame = static_cast<HTMLFrameOwnerElement*>(node)->contentFrame())) { - RefPtr<LegacyWebArchive> subframeArchive = create(childFrame->document()); - - if (subframeArchive) - subframeArchives.append(subframeArchive); - else - LOG_ERROR("Unabled to archive subframe %s", childFrame->tree()->uniqueName().string().utf8().data()); - } else { - ListHashSet<KURL> subresourceURLs; - node->getSubresourceURLs(subresourceURLs); - - DocumentLoader* documentLoader = frame->loader()->documentLoader(); - ListHashSet<KURL>::iterator iterEnd = subresourceURLs.end(); - for (ListHashSet<KURL>::iterator iter = subresourceURLs.begin(); iter != iterEnd; ++iter) { - const KURL& subresourceURL = *iter; - if (uniqueSubresources.contains(subresourceURL)) - continue; - - uniqueSubresources.add(subresourceURL); - - RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL); - if (resource) { - subresources.append(resource.release()); - continue; - } - - CachedResource *cachedResource = cache()->resourceForURL(subresourceURL); - if (cachedResource) { - resource = ArchiveResource::create(cachedResource->data(), subresourceURL, cachedResource->response()); - if (resource) { - subresources.append(resource.release()); - continue; - } - } - - // FIXME: should do something better than spew to console here - LOG_ERROR("Failed to archive subresource for %s", subresourceURL.string().utf8().data()); - } - } - } - - // Add favicon if one exists for this page, if we are archiving the entire page. - if (nodesSize && nodes[0]->isDocumentNode() && iconDatabase() && iconDatabase()->isEnabled()) { - const String& iconURL = iconDatabase()->iconURLForPageURL(responseURL); - if (!iconURL.isEmpty() && iconDatabase()->iconDataKnownForIconURL(iconURL)) { - if (Image* iconImage = iconDatabase()->iconForPageURL(responseURL, IntSize(16, 16))) { - if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(ParsedURLString, iconURL), "image/x-icon", "", "")) - subresources.append(resource.release()); - } - } - } - - return create(mainResource, subresources, subframeArchives); -} - -PassRefPtr<LegacyWebArchive> LegacyWebArchive::createFromSelection(Frame* frame) -{ - if (!frame) - return 0; - - RefPtr<Range> selectionRange = frame->selection()->toNormalizedRange(); - Vector<Node*> nodeList; - String markupString = frame->documentTypeString() + createMarkup(selectionRange.get(), &nodeList, AnnotateForInterchange); - - RefPtr<LegacyWebArchive> archive = create(markupString, frame, nodeList); - - if (!frame->document() || !frame->document()->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 = makeString("<iframe frameborder=\"no\" marginwidth=\"0\" marginheight=\"0\" width=\"98%%\" height=\"98%%\" src=\"", - frame->loader()->documentLoader()->response().url().string(), "\"></iframe>"); - 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 = 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 8c8f2e4..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchive.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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" - -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*); - static PassRefPtr<LegacyWebArchive> create(Range*); - - RetainPtr<CFDataRef> rawDataRepresentation(); - -private: - LegacyWebArchive() { } - - enum MainResourceStatus { Subresource, MainResource }; - - static PassRefPtr<LegacyWebArchive> create(const String& markupString, Frame*, const Vector<Node*>& nodes); - static PassRefPtr<ArchiveResource> createResource(CFDictionaryRef); - static ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef); - static ResourceResponse createResourceResponseFromPropertyListData(CFDataRef, CFStringRef responseDataType); - static RetainPtr<CFDataRef> createPropertyListRepresentation(const ResourceResponse&); - static RetainPtr<CFDictionaryRef> createPropertyListRepresentation(Archive*); - static RetainPtr<CFDictionaryRef> createPropertyListRepresentation(ArchiveResource*, MainResourceStatus); - - bool extract(CFDictionaryRef); -}; - -} - -#endif // Archive diff --git a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm b/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm deleted file mode 100644 index 6a35753..0000000 --- a/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2008, 2009 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 NSString * const LegacyWebArchiveResourceResponseKey = @"WebResourceResponse"; - -// FIXME: If is is possible to parse in a serialized NSURLResponse manually, without using -// NSKeyedUnarchiver, manipulating plists directly, we would prefer to do that instead. -ResourceResponse LegacyWebArchive::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> LegacyWebArchive::createPropertyListRepresentation(const ResourceResponse& response) -{ - NSURLResponse *nsResponse = response.nsURLResponse(); - ASSERT(nsResponse); - if (!nsResponse) - return 0; - - CFMutableDataRef responseData = CFDataCreateMutable(0, 0); - - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:(NSMutableData *)responseData]; - [archiver encodeObject:nsResponse forKey:LegacyWebArchiveResourceResponseKey]; - [archiver finishEncoding]; - [archiver release]; - - return RetainPtr<CFDataRef>(AdoptCF, responseData); -} - -} diff --git a/WebCore/loader/cache/CachePolicy.h b/WebCore/loader/cache/CachePolicy.h deleted file mode 100644 index 0b9010b..0000000 --- a/WebCore/loader/cache/CachePolicy.h +++ /dev/null @@ -1,41 +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, - CachePolicyRevalidate, - CachePolicyReload, - CachePolicyHistoryBuffer - }; - -} - -#endif diff --git a/WebCore/loader/cache/CachedCSSStyleSheet.cpp b/WebCore/loader/cache/CachedCSSStyleSheet.cpp deleted file mode 100644 index ae7a03c..0000000 --- a/WebCore/loader/cache/CachedCSSStyleSheet.cpp +++ /dev/null @@ -1,151 +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 "MemoryCache.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "HTTPParsers.h" -#include "TextResourceDecoder.h" -#include "SharedBuffer.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::didAddClient(CachedResourceClient *c) -{ - if (!isLoading()) - c->setCSSStyleSheet(m_url, m_response.url(), m_decoder->encoding().name(), this); -} - -void CachedCSSStyleSheet::allClientsRemoved() -{ - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable()) - makePurgeable(true); -} - -void CachedCSSStyleSheet::setEncoding(const String& chs) -{ - m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader); -} - -String CachedCSSStyleSheet::encoding() const -{ - return m_decoder->encoding().name(); -} - -const String CachedCSSStyleSheet::sheetText(bool enforceMIMEType, bool* hasValidMIMEType) const -{ - ASSERT(!isPurgeable()); - - if (!m_data || m_data->isEmpty() || !canUseSheet(enforceMIMEType, hasValidMIMEType)) - return String(); - - if (!m_decodedSheetText.isNull()) - return m_decodedSheetText; - - // Don't cache the decoded text, regenerating is cheap and it can use quite a bit of memory - String sheetText = m_decoder->decode(m_data->data(), m_data->size()); - sheetText += m_decoder->flush(); - return sheetText; -} - -void CachedCSSStyleSheet::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - // Decode the data to find out the encoding and keep the sheet text around during checkNotify() - if (m_data) { - m_decodedSheetText = m_decoder->decode(m_data->data(), m_data->size()); - m_decodedSheetText += m_decoder->flush(); - } - setLoading(false); - checkNotify(); - // Clear the decoded text as it is unlikely to be needed immediately again and is cheap to regenerate. - m_decodedSheetText = String(); -} - -void CachedCSSStyleSheet::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->setCSSStyleSheet(m_url, m_response.url(), m_decoder->encoding().name(), this); -} - -void CachedCSSStyleSheet::error(CachedResource::Status status) -{ - setStatus(status); - ASSERT(errorOccurred()); - setLoading(false); - checkNotify(); -} - -bool CachedCSSStyleSheet::canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const -{ - if (errorOccurred()) - return false; - - if (!enforceMIMEType && !hasValidMIMEType) - return true; - - // This check exactly matches Firefox. Note that we grab the Content-Type - // header directly because we want to see what the value is BEFORE content - // sniffing. Firefox does this by setting a "type hint" on the channel. - // This implementation should be observationally equivalent. - // - // This code defaults to allowing the stylesheet for non-HTTP protocols so - // folks can use standards mode for local HTML documents. - String mimeType = extractMIMETypeFromMediaType(response().httpHeaderField("Content-Type")); - bool typeOK = mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type"); - if (hasValidMIMEType) - *hasValidMIMEType = typeOK; - if (!enforceMIMEType) - return true; - return typeOK; -} - -} diff --git a/WebCore/loader/cache/CachedCSSStyleSheet.h b/WebCore/loader/cache/CachedCSSStyleSheet.h deleted file mode 100644 index a982e03..0000000 --- a/WebCore/loader/cache/CachedCSSStyleSheet.h +++ /dev/null @@ -1,67 +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, 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 CachedCSSStyleSheet_h -#define CachedCSSStyleSheet_h - -#include "CachedResource.h" -#include "TextEncoding.h" -#include <wtf/Vector.h> - -namespace WebCore { - - class CachedResourceLoader; - class TextResourceDecoder; - - class CachedCSSStyleSheet : public CachedResource { - public: - CachedCSSStyleSheet(const String& URL, const String& charset); - virtual ~CachedCSSStyleSheet(); - - const String sheetText(bool enforceMIMEType = true, bool* hasValidMIMEType = 0) const; - - virtual void didAddClient(CachedResourceClient*); - - virtual void allClientsRemoved(); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status); - - void checkNotify(); - - private: - bool canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const; - virtual PurgePriority purgePriority() const { return PurgeLast; } - - protected: - RefPtr<TextResourceDecoder> m_decoder; - String m_decodedSheetText; - }; - -} - -#endif diff --git a/WebCore/loader/cache/CachedFont.cpp b/WebCore/loader/cache/CachedFont.cpp deleted file mode 100644 index d6967bf..0000000 --- a/WebCore/loader/cache/CachedFont.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Torch Mobile, Inc. - * - * 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" - -#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (OS(WINDOWS) || OS(LINUX) || OS(FREEBSD))) || PLATFORM(HAIKU) || OS(WINCE) || PLATFORM(ANDROID) || PLATFORM(BREWMP) -#define STORE_FONT_CUSTOM_PLATFORM_DATA -#endif - -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "CachedResourceLoader.h" -#include "FontPlatformData.h" -#include "MemoryCache.h" -#include "SharedBuffer.h" -#include "TextResourceDecoder.h" -#include <wtf/Vector.h> - -#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA -#include "FontCustomPlatformData.h" -#endif - -#if ENABLE(SVG_FONTS) -#include "NodeList.h" -#include "SVGElement.h" -#include "SVGFontElement.h" -#include "SVGGElement.h" -#include "SVGNames.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() -{ -#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA - delete m_fontData; -#endif -} - -void CachedFont::load(CachedResourceLoader*) -{ - // Don't load the file yet. Wait for an access before triggering the load. - setLoading(true); -} - -void CachedFont::didAddClient(CachedResourceClient* c) -{ - if (!isLoading()) - 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); - setLoading(false); - checkNotify(); -} - -void CachedFont::beginLoadIfNeeded(CachedResourceLoader* dl) -{ - if (!m_loadInitiated) { - m_loadInitiated = true; - dl->load(this, false); - } -} - -bool CachedFont::ensureCustomFontData() -{ -#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA -#if ENABLE(SVG_FONTS) - ASSERT(!m_isSVGFont); -#endif - if (!m_fontData && !errorOccurred() && !isLoading() && m_data) { - m_fontData = createFontCustomPlatformData(m_data.get()); - if (!m_fontData) - setStatus(DecodeError); - } -#endif - return m_fontData; -} - -FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode renderingMode) -{ -#if ENABLE(SVG_FONTS) - if (m_externalSVGDocument) - return FontPlatformData(size, bold, italic); -#endif -#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA - ASSERT(m_fontData); - return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, renderingMode); -#else - return FontPlatformData(); -#endif -} - -#if ENABLE(SVG_FONTS) -bool CachedFont::ensureSVGFontData() -{ - ASSERT(m_isSVGFont); - if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) { - m_externalSVGDocument = SVGDocument::create(0, KURL()); - m_externalSVGDocument->open(); - - RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml"); - m_externalSVGDocument->write(decoder->decode(m_data->data(), m_data->size())); - m_externalSVGDocument->write(decoder->flush()); - 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->getElementsByTagNameNS(SVGNames::fontTag.namespaceURI(), SVGNames::fontTag.localName()); - if (!list) - return 0; - - unsigned listLength = list->length(); - if (!listLength) - return 0; - -#ifndef NDEBUG - for (unsigned i = 0; i < listLength; ++i) { - ASSERT(list->item(i)); - ASSERT(list->item(i)->hasTagName(SVGNames::fontTag)); - } -#endif - - if (fontName.isEmpty()) - return static_cast<SVGFontElement*>(list->item(0)); - - for (unsigned i = 0; i < listLength; ++i) { - SVGFontElement* element = static_cast<SVGFontElement*>(list->item(i)); - if (element->getIdAttribute() == fontName) - return element; - } - - return 0; -} -#endif - -void CachedFont::allClientsRemoved() -{ -#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA - if (m_fontData) { - delete m_fontData; - m_fontData = 0; - } -#endif -} - -void CachedFont::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->fontLoaded(this); -} - - -void CachedFont::error(CachedResource::Status status) -{ - setStatus(status); - ASSERT(errorOccurred()); - setLoading(false); - checkNotify(); -} - -} diff --git a/WebCore/loader/cache/CachedFont.h b/WebCore/loader/cache/CachedFont.h deleted file mode 100644 index 5814087..0000000 --- a/WebCore/loader/cache/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 "FontOrientation.h" -#include "FontRenderingMode.h" -#include <wtf/Vector.h> - -#if ENABLE(SVG_FONTS) -#include "SVGElement.h" -#include "SVGDocument.h" -#endif - -namespace WebCore { - -class CachedResourceLoader; -class MemoryCache; -class FontPlatformData; -class SVGFontElement; - -struct FontCustomPlatformData; - -class CachedFont : public CachedResource { -public: - CachedFont(const String& url); - virtual ~CachedFont(); - - virtual void load(CachedResourceLoader* cachedResourceLoader); - - virtual void didAddClient(CachedResourceClient*); - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status); - - virtual void allClientsRemoved(); - - void checkNotify(); - - void beginLoadIfNeeded(CachedResourceLoader* dl); - - bool ensureCustomFontData(); - FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation = Horizontal, 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 MemoryCache; -}; - -} - -#endif diff --git a/WebCore/loader/cache/CachedImage.cpp b/WebCore/loader/cache/CachedImage.cpp deleted file mode 100644 index ccc34c1..0000000 --- a/WebCore/loader/cache/CachedImage.cpp +++ /dev/null @@ -1,391 +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 "MemoryCache.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "CachedResourceLoader.h" -#include "Frame.h" -#include "FrameLoaderTypes.h" -#include "FrameView.h" -#include "Settings.h" -#include "SharedBuffer.h" -#include <wtf/CurrentTime.h> -#include <wtf/StdLibExtras.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) -{ - setStatus(Unknown); -} - -CachedImage::CachedImage(Image* image) - : CachedResource(String(), ImageResource) - , m_image(image) - , m_decodedDataDeletionTimer(this, &CachedImage::decodedDataDeletionTimerFired) -{ - setStatus(Cached); - setLoading(false); -} - -CachedImage::~CachedImage() -{ -} - -void CachedImage::decodedDataDeletionTimerFired(Timer<CachedImage>*) -{ - ASSERT(!hasClients()); - destroyDecodedData(); -} - -void CachedImage::load(CachedResourceLoader* cachedResourceLoader) -{ -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (!cachedResourceLoader || (cachedResourceLoader->autoLoadImages() && !cachedResourceLoader->shouldBlockNetworkImage(m_url))) -#else - if (!cachedResourceLoader || cachedResourceLoader->autoLoadImages()) -#endif - CachedResource::load(cachedResourceLoader, true, DoSecurityCheck, true); - else - setLoading(false); -} - -void CachedImage::didAddClient(CachedResourceClient* c) -{ - if (m_decodedDataDeletionTimer.isActive()) - m_decodedDataDeletionTimer.stop(); - - if (m_data && !m_image && !errorOccurred()) { - createImage(); - m_image->setData(m_data, true); - } - - if (m_image && !m_image->isNull()) - c->imageChanged(this); - - if (!isLoading()) - c->notifyFinished(this); -} - -void CachedImage::allClientsRemoved() -{ - if (m_image && !errorOccurred()) - m_image->resetAnimation(); - if (double interval = cache()->deadDecodedDataDeletionInterval()) - m_decodedDataDeletionTimer.startOneShot(interval); -} - -static Image* brokenImage() -{ - DEFINE_STATIC_LOCAL(RefPtr<Image>, brokenImage, (Image::loadPlatformResource("missingImage"))); - return brokenImage.get(); -} - -static Image* nullImage() -{ - DEFINE_STATIC_LOCAL(RefPtr<BitmapImage>, nullImage, (BitmapImage::create())); - return nullImage.get(); -} - -Image* CachedImage::image() const -{ - ASSERT(!isPurgeable()); - - if (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 -{ - ASSERT(!isPurgeable()); - - 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 -{ - ASSERT(!isPurgeable()); - - 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(const IntRect* changeRect) -{ - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->imageChanged(this, changeRect); -} - -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) && !USE(WEBKIT_IMAGE_DECODERS) - 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(ANDROID) - m_image->setURL(url()); -#endif -} - -size_t CachedImage::maximumDecodedImageSize() -{ - Frame* frame = m_request ? m_request->cachedResourceLoader()->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(errorOccurred() ? status() : DecodeError); - if (inCache()) - cache()->remove(this); - return; - } - - // It would be nice to only redraw the decoded band of the image, but with the current design - // (decoding delayed until painting) that seems hard. - notifyObservers(); - - if (m_image) - setEncodedSize(m_image->data() ? m_image->data()->size() : 0); - } - - if (allDataReceived) { - setLoading(false); - checkNotify(); - } -} - -void CachedImage::error(CachedResource::Status status) -{ - clear(); - setStatus(status); - ASSERT(errorOccurred()); - m_data.clear(); - notifyObservers(); - setLoading(false); - checkNotify(); -} - -void CachedImage::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - -void CachedImage::destroyDecodedData() -{ - bool canDeleteImage = !m_image || (m_image->hasOneRef() && m_image->isBitmapImage()); - if (isSafeToMakePurgeable() && canDeleteImage && !isLoading()) { - // Image refs the data buffer so we should not make it purgeable while the image is alive. - // Invoking addClient() will reconstruct the image object. - m_image = 0; - setDecodedSize(0); - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction()) - makePurgeable(true); - } else if (m_image && !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(); -} - -void CachedImage::changedInRect(const Image* image, const IntRect& rect) -{ - if (image == m_image) - notifyObservers(&rect); -} - -} //namespace WebCore diff --git a/WebCore/loader/cache/CachedImage.h b/WebCore/loader/cache/CachedImage.h deleted file mode 100644 index e889ea0..0000000 --- a/WebCore/loader/cache/CachedImage.h +++ /dev/null @@ -1,104 +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 "IntRect.h" -#include "Timer.h" -#include <wtf/Vector.h> - -namespace WebCore { - -class CachedResourceLoader; -class MemoryCache; - -class CachedImage : public CachedResource, public ImageObserver { - friend class MemoryCache; - -public: - CachedImage(const String& url); - CachedImage(Image*); - virtual ~CachedImage(); - - virtual void load(CachedResourceLoader* cachedResourceLoader); - - 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 didAddClient(CachedResourceClient*); - - virtual void allClientsRemoved(); - virtual void destroyDecodedData(); - - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status); - - // For compatibility, images keep loading even if there are HTTP errors. - virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return true; } - - void checkNotify(); - - virtual bool isImage() const { return true; } - - void clear(); - - bool stillNeedsLoad() const { return !errorOccurred() && status() == Unknown && !isLoading(); } - 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*); - virtual void changedInRect(const Image*, const IntRect&); - -private: - void createImage(); - size_t maximumDecodedImageSize(); - // If not null, changeRect is the changed part of the image. - void notifyObservers(const IntRect* changeRect = 0); - void decodedDataDeletionTimerFired(Timer<CachedImage>*); - virtual PurgePriority purgePriority() const { return PurgeFirst; } - - RefPtr<Image> m_image; - Timer<CachedImage> m_decodedDataDeletionTimer; -}; - -} - -#endif diff --git a/WebCore/loader/cache/CachedResource.cpp b/WebCore/loader/cache/CachedResource.cpp deleted file mode 100644 index 19e535f..0000000 --- a/WebCore/loader/cache/CachedResource.cpp +++ /dev/null @@ -1,591 +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 "CachedResource.h" - -#include "MemoryCache.h" -#include "CachedMetadata.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "CachedResourceHandle.h" -#include "CachedResourceLoader.h" -#include "CachedResourceRequest.h" -#include "Frame.h" -#include "FrameLoaderClient.h" -#include "KURL.h" -#include "Logging.h" -#include "PurgeableBuffer.h" -#include "ResourceHandle.h" -#include "SharedBuffer.h" -#include <wtf/CurrentTime.h> -#include <wtf/MathExtras.h> -#include <wtf/RefCountedLeakCounter.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Vector.h> - -using namespace WTF; - -namespace WebCore { - -static ResourceLoadPriority defaultPriorityForResourceType(CachedResource::Type type) -{ - switch (type) { - case CachedResource::CSSStyleSheet: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif - return ResourceLoadPriorityHigh; - case CachedResource::Script: - case CachedResource::FontResource: - return ResourceLoadPriorityMedium; - case CachedResource::ImageResource: - return ResourceLoadPriorityLow; -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: - return ResourceLoadPriorityVeryLow; -#endif - } - ASSERT_NOT_REACHED(); - return ResourceLoadPriorityLow; -} - -#ifndef NDEBUG -static RefCountedLeakCounter cachedResourceLeakCounter("CachedResource"); -#endif - -CachedResource::CachedResource(const String& url, Type type) - : m_url(url) - , m_request(0) - , m_loadPriority(defaultPriorityForResourceType(type)) - , m_responseTimestamp(currentTime()) - , m_lastDecodedAccessTime(0) - , m_encodedSize(0) - , m_decodedSize(0) - , m_accessCount(0) - , m_handleCount(0) - , m_preloadCount(0) - , m_preloadResult(PreloadNotReferenced) - , m_inLiveDecodedResourcesList(false) - , m_requestedFromNetworkingLayer(false) - , m_sendResourceLoadCallbacks(true) - , m_inCache(false) - , m_loading(false) - , m_type(type) - , m_status(Pending) -#ifndef NDEBUG - , m_deleted(false) - , m_lruIndex(0) -#endif - , m_nextInAllResourcesList(0) - , m_prevInAllResourcesList(0) - , m_nextInLiveResourcesList(0) - , m_prevInLiveResourcesList(0) - , m_cachedResourceLoader(0) - , m_resourceToRevalidate(0) - , m_proxyResource(0) -{ -#ifndef NDEBUG - cachedResourceLeakCounter.increment(); -#endif -} - -CachedResource::~CachedResource() -{ - ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() checks this. - ASSERT(canDelete()); - ASSERT(!inCache()); - ASSERT(!m_deleted); - ASSERT(url().isNull() || cache()->resourceForURL(KURL(ParsedURLString, url())) != this); -#ifndef NDEBUG - m_deleted = true; - cachedResourceLeakCounter.decrement(); -#endif - - if (m_cachedResourceLoader) - m_cachedResourceLoader->removeCachedResource(this); -} - -void CachedResource::load(CachedResourceLoader* cachedResourceLoader, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) -{ - m_sendResourceLoadCallbacks = sendResourceLoadCallbacks; - cachedResourceLoader->load(this, incremental, securityCheck, sendResourceLoadCallbacks); - m_loading = true; -} - -void CachedResource::data(PassRefPtr<SharedBuffer>, bool allDataReceived) -{ - if (!allDataReceived) - return; - - setLoading(false); - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - -void CachedResource::finish() -{ - m_status = Cached; -} - -bool CachedResource::isExpired() const -{ - if (m_response.isNull()) - return false; - - return currentAge() > freshnessLifetime(); -} - -double CachedResource::currentAge() const -{ - // RFC2616 13.2.3 - // No compensation for latency as that is not terribly important in practice - double dateValue = m_response.date(); - double apparentAge = isfinite(dateValue) ? max(0., m_responseTimestamp - dateValue) : 0; - double ageValue = m_response.age(); - double correctedReceivedAge = isfinite(ageValue) ? max(apparentAge, ageValue) : apparentAge; - double residentTime = currentTime() - m_responseTimestamp; - return correctedReceivedAge + residentTime; -} - -double CachedResource::freshnessLifetime() const -{ - // Cache non-http resources liberally - if (!m_response.url().protocolInHTTPFamily()) - return std::numeric_limits<double>::max(); - - // RFC2616 13.2.4 - double maxAgeValue = m_response.cacheControlMaxAge(); - if (isfinite(maxAgeValue)) - return maxAgeValue; - double expiresValue = m_response.expires(); - double dateValue = m_response.date(); - double creationTime = isfinite(dateValue) ? dateValue : m_responseTimestamp; - if (isfinite(expiresValue)) - return expiresValue - creationTime; - double lastModifiedValue = m_response.lastModified(); - if (isfinite(lastModifiedValue)) - return (creationTime - lastModifiedValue) * 0.1; - // If no cache headers are present, the specification leaves the decision to the UA. Other browsers seem to opt for 0. - return 0; -} - -void CachedResource::setResponse(const ResourceResponse& response) -{ - m_response = response; - m_responseTimestamp = currentTime(); -} - -void CachedResource::setSerializedCachedMetadata(const char* data, size_t size) -{ - // We only expect to receive cached metadata from the platform once. - // If this triggers, it indicates an efficiency problem which is most - // likely unexpected in code designed to improve performance. - ASSERT(!m_cachedMetadata); - - m_cachedMetadata = CachedMetadata::deserialize(data, size); -} - -void CachedResource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size) -{ - // Currently, only one type of cached metadata per resource is supported. - // If the need arises for multiple types of metadata per resource this could - // be enhanced to store types of metadata in a map. - ASSERT(!m_cachedMetadata); - - m_cachedMetadata = CachedMetadata::create(dataTypeID, data, size); - ResourceHandle::cacheMetadata(m_response, m_cachedMetadata->serialize()); -} - -CachedMetadata* CachedResource::cachedMetadata(unsigned dataTypeID) const -{ - if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID) - return 0; - return m_cachedMetadata.get(); -} - -void CachedResource::setRequest(CachedResourceRequest* request) -{ - if (request && !m_request) - m_status = Pending; - m_request = request; - if (canDelete() && !inCache()) - delete this; -} - -void CachedResource::addClient(CachedResourceClient* client) -{ - addClientToSet(client); - didAddClient(client); -} - -void CachedResource::didAddClient(CachedResourceClient* c) -{ - if (!isLoading()) - c->notifyFinished(this); -} - -void CachedResource::addClientToSet(CachedResourceClient* client) -{ - ASSERT(!isPurgeable()); - - if (m_preloadResult == PreloadNotReferenced) { - if (isLoaded()) - m_preloadResult = PreloadReferencedWhileComplete; - else if (m_requestedFromNetworkingLayer) - m_preloadResult = PreloadReferencedWhileLoading; - else - m_preloadResult = PreloadReferenced; - } - if (!hasClients() && inCache()) - cache()->addToLiveResourcesSize(this); - m_clients.add(client); -} - -void CachedResource::removeClient(CachedResourceClient* client) -{ - ASSERT(m_clients.contains(client)); - m_clients.remove(client); - - if (canDelete() && !inCache()) - delete this; - else if (!hasClients() && inCache()) { - cache()->removeFromLiveResourcesSize(this); - cache()->removeFromLiveDecodedResourcesList(this); - allClientsRemoved(); - if (response().cacheControlContainsNoStore()) { - // RFC2616 14.9.2: - // "no-store: ... MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible" - // "... History buffers MAY store such responses as part of their normal operation." - // We allow non-secure content to be reused in history, but we do not allow secure content to be reused. - if (protocolIs(url(), "https")) - cache()->remove(this); - } else - cache()->prune(); - } - // This object may be dead here. -} - -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. - // When inserting into the LiveDecodedResourcesList it is possible - // that the m_lastDecodedAccessTime is still zero or smaller than - // the m_lastDecodedAccessTime of the current list head. This is a - // violation of the invariant that the list is to be kept sorted - // by access time. The weakening of the invariant does not pose - // a problem. For more details please see: https://bugs.webkit.org/show_bug.cgi?id=30209 - 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(m_handlesToRevalidate.isEmpty()); - ASSERT(resource->type() == type()); - - LOG(ResourceLoading, "CachedResource %p setResourceToRevalidate %p", this, resource); - - // The following assert should be investigated whenever it occurs. Although it should never fire, it currently does in rare circumstances. - // https://bugs.webkit.org/show_bug.cgi?id=28604. - // So the code needs to be robust to this assert failing thus the "if (m_resourceToRevalidate->m_proxyResource == this)" in CachedResource::clearResourceToRevalidate. - ASSERT(!resource->m_proxyResource); - - resource->m_proxyResource = this; - m_resourceToRevalidate = resource; -} - -void CachedResource::clearResourceToRevalidate() -{ - ASSERT(m_resourceToRevalidate); - // A resource may start revalidation before this method has been called, so check that this resource is still the proxy resource before clearing it out. - if (m_resourceToRevalidate->m_proxyResource == this) { - m_resourceToRevalidate->m_proxyResource = 0; - m_resourceToRevalidate->deleteIfPossible(); - } - m_handlesToRevalidate.clear(); - m_resourceToRevalidate = 0; - deleteIfPossible(); -} - -void CachedResource::switchClientsToRevalidatedResource() -{ - ASSERT(m_resourceToRevalidate); - ASSERT(m_resourceToRevalidate->inCache()); - ASSERT(!inCache()); - - LOG(ResourceLoading, "CachedResource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate); - - 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->addClientToSet(clientsToMove[n]); - for (unsigned n = 0; n < moveCount; ++n) { - // Calling didAddClient for a client may end up removing another client. In that case it won't be in the set anymore. - if (m_resourceToRevalidate->m_clients.contains(clientsToMove[n])) - m_resourceToRevalidate->didAddClient(clientsToMove[n]); - } -} - -void CachedResource::updateResponseAfterRevalidation(const ResourceResponse& validatingResponse) -{ - m_responseTimestamp = currentTime(); - - DEFINE_STATIC_LOCAL(const AtomicString, contentHeaderPrefix, ("content-")); - // RFC2616 10.3.5 - // Update cached headers from the 304 response - const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields(); - HTTPHeaderMap::const_iterator end = newHeaders.end(); - for (HTTPHeaderMap::const_iterator it = newHeaders.begin(); it != end; ++it) { - // Don't allow 304 response to update content headers, these can't change but some servers send wrong values. - if (it->first.startsWith(contentHeaderPrefix, false)) - continue; - m_response.setHTTPHeaderField(it->first, it->second); - } -} - -void CachedResource::registerHandle(CachedResourceHandleBase* h) -{ - ++m_handleCount; - if (m_resourceToRevalidate) - m_handlesToRevalidate.add(h); -} - -void CachedResource::unregisterHandle(CachedResourceHandleBase* h) -{ - ASSERT(m_handleCount > 0); - --m_handleCount; - - if (m_resourceToRevalidate) - m_handlesToRevalidate.remove(h); - - if (!m_handleCount) - deleteIfPossible(); -} - -bool CachedResource::canUseCacheValidator() const -{ - if (m_loading || errorOccurred()) - return false; - - if (m_response.cacheControlContainsNoStore()) - return false; - - DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified")); - DEFINE_STATIC_LOCAL(const AtomicString, eTagHeader, ("etag")); - return !m_response.httpHeaderField(lastModifiedHeader).isEmpty() || !m_response.httpHeaderField(eTagHeader).isEmpty(); -} - -bool CachedResource::mustRevalidate(CachePolicy cachePolicy) const -{ - if (errorOccurred()) { - LOG(ResourceLoading, "CachedResource %p mustRevalidate because of m_errorOccurred\n", this); - return true; - } - - if (m_loading) - return false; - - if (m_response.cacheControlContainsNoCache() || m_response.cacheControlContainsNoStore()) { - LOG(ResourceLoading, "CachedResource %p mustRevalidate because of m_response.cacheControlContainsNoCache() || m_response.cacheControlContainsNoStore()\n", this); - return true; - } - - if (cachePolicy == CachePolicyCache) { - if (m_response.cacheControlContainsMustRevalidate() && isExpired()) { - LOG(ResourceLoading, "CachedResource %p mustRevalidate because of cachePolicy == CachePolicyCache and m_response.cacheControlContainsMustRevalidate() && isExpired()\n", this); - return true; - } - return false; - } - - if (isExpired()) { - LOG(ResourceLoading, "CachedResource %p mustRevalidate because of isExpired()\n", this); - return true; - } - - return false; -} - -bool CachedResource::isSafeToMakePurgeable() const -{ - return !hasClients() && !m_proxyResource && !m_resourceToRevalidate; -} - -bool CachedResource::makePurgeable(bool purgeable) -{ - if (purgeable) { - ASSERT(isSafeToMakePurgeable()); - - if (m_purgeableData) { - ASSERT(!m_data); - return true; - } - if (!m_data) - return false; - - // Should not make buffer purgeable if it has refs other than this since we don't want two copies. - if (!m_data->hasOneRef()) - return false; - - if (m_data->hasPurgeableBuffer()) { - m_purgeableData = m_data->releasePurgeableBuffer(); - } else { - m_purgeableData = PurgeableBuffer::create(m_data->data(), m_data->size()); - if (!m_purgeableData) - return false; - m_purgeableData->setPurgePriority(purgePriority()); - } - - m_purgeableData->makePurgeable(true); - m_data.clear(); - return true; - } - - if (!m_purgeableData) - return true; - ASSERT(!m_data); - ASSERT(!hasClients()); - - if (!m_purgeableData->makePurgeable(false)) - return false; - - m_data = SharedBuffer::adoptPurgeableBuffer(m_purgeableData.release()); - return true; -} - -bool CachedResource::isPurgeable() const -{ - return m_purgeableData && m_purgeableData->isPurgeable(); -} - -bool CachedResource::wasPurged() const -{ - return m_purgeableData && m_purgeableData->wasPurged(); -} - -unsigned CachedResource::overheadSize() const -{ - return sizeof(CachedResource) + m_response.memoryUsage() + 576; - /* - 576 = 192 + // average size of m_url - 384; // average size of m_clients hash map - */ -} - -} diff --git a/WebCore/loader/cache/CachedResource.h b/WebCore/loader/cache/CachedResource.h deleted file mode 100644 index 9defc16..0000000 --- a/WebCore/loader/cache/CachedResource.h +++ /dev/null @@ -1,295 +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 "FrameLoaderTypes.h" -#include "PlatformString.h" -#include "PurgePriority.h" -#include "ResourceLoadPriority.h" -#include "ResourceResponse.h" -#include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#include <wtf/Vector.h> -#include <time.h> - -namespace WebCore { - -class MemoryCache; -class CachedMetadata; -class CachedResourceClient; -class CachedResourceHandleBase; -class CachedResourceLoader; -class CachedResourceRequest; -class Frame; -class InspectorResource; -class PurgeableBuffer; - -// 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 : public Noncopyable { - friend class MemoryCache; - friend class InspectorResource; - -public: - enum Type { - ImageResource, - CSSStyleSheet, - Script, - FontResource -#if ENABLE(XSLT) - , XSLStyleSheet -#endif -#if ENABLE(LINK_PREFETCH) - , LinkPrefetch -#endif - }; - - enum Status { - Unknown, // let cache decide what to do with it - Pending, // only partially loaded - Cached, // regular case - LoadError, - DecodeError - }; - - CachedResource(const String& url, Type); - virtual ~CachedResource(); - - virtual void load(CachedResourceLoader* cachedResourceLoader) { load(cachedResourceLoader, false, DoSecurityCheck, true); } - void load(CachedResourceLoader*, bool incremental, SecurityCheckPolicy, bool sendResourceLoadCallbacks); - - virtual void setEncoding(const String&) { } - virtual String encoding() const { return String(); } - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status) { } - - virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; } - - const String &url() const { return m_url; } - Type type() const { return static_cast<Type>(m_type); } - - ResourceLoadPriority loadPriority() const { return m_loadPriority; } - - 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 static_cast<PreloadResult>(m_preloadResult); } - void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; } - - virtual void didAddClient(CachedResourceClient*); - virtual void allClientsRemoved() { } - - unsigned count() const { return m_clients.size(); } - - Status status() const { return static_cast<Status>(m_status); } - void setStatus(Status status) { m_status = status; } - - unsigned size() const { return encodedSize() + decodedSize() + overheadSize(); } - unsigned encodedSize() const { return m_encodedSize; } - unsigned decodedSize() const { return m_decodedSize; } - unsigned overheadSize() const; - - bool isLoaded() const { return !m_loading; } // FIXME. Method name is inaccurate. Loading might not have started yet. - - bool isLoading() const { return m_loading; } - void setLoading(bool b) { m_loading = b; } - - virtual bool isImage() const { return false; } - bool isPrefetch() const - { -#if ENABLE(LINK_PREFETCH) - return type() == LinkPrefetch; -#else - return false; -#endif - } - - 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. - // The resource can be brought back to cache after successful revalidation. - void setInCache(bool inCache) { m_inCache = inCache; } - bool inCache() const { return m_inCache; } - - void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } - bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } - - void setRequest(CachedResourceRequest*); - - SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); } - - void setResponse(const ResourceResponse&); - const ResourceResponse& response() const { return m_response; } - - // Sets the serialized metadata retrieved from the platform's cache. - void setSerializedCachedMetadata(const char*, size_t); - - // Caches the given metadata in association with this resource and suggests - // that the platform persist it. The dataTypeID is a pseudo-randomly chosen - // identifier that is used to distinguish data generated by the caller. - void setCachedMetadata(unsigned dataTypeID, const char*, size_t); - - // Returns cached metadata of the given type associated with this resource. - CachedMetadata* cachedMetadata(unsigned dataTypeID) const; - - bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_proxyResource; } - - bool isExpired() const; - - // List of acceptable MIME types separated 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 (status() == LoadError || status() == DecodeError); } - - bool sendResourceLoadCallbacks() const { return m_sendResourceLoadCallbacks; } - - virtual void destroyDecodedData() { } - - void setCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) { m_cachedResourceLoader = cachedResourceLoader; } - - bool isPreloaded() const { return m_preloadCount; } - void increasePreloadCount() { ++m_preloadCount; } - void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } - - void registerHandle(CachedResourceHandleBase* h); - void unregisterHandle(CachedResourceHandleBase* h); - - bool canUseCacheValidator() const; - bool mustRevalidate(CachePolicy) const; - bool isCacheValidator() const { return m_resourceToRevalidate; } - CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } - - bool isPurgeable() const; - bool wasPurged() const; - - // This is used by the archive machinery to get at a purged resource without - // triggering a load. We should make it protected again if we can find a - // better way to handle the archive case. - bool makePurgeable(bool purgeable); - -protected: - void setEncodedSize(unsigned); - void setDecodedSize(unsigned); - void didAccessDecodedData(double timeStamp); - - bool isSafeToMakePurgeable() const; - - HashCountedSet<CachedResourceClient*> m_clients; - - String m_url; - String m_accept; - CachedResourceRequest* m_request; - ResourceLoadPriority m_loadPriority; - - ResourceResponse m_response; - double m_responseTimestamp; - - RefPtr<SharedBuffer> m_data; - OwnPtr<PurgeableBuffer> m_purgeableData; - -private: - void addClientToSet(CachedResourceClient*); - - // These are called by the friendly MemoryCache only - void setResourceToRevalidate(CachedResource*); - void switchClientsToRevalidatedResource(); - void clearResourceToRevalidate(); - void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); - virtual PurgePriority purgePriority() const { return PurgeDefault; } - void setLoadPriority(ResourceLoadPriority loadPriority) { m_loadPriority = loadPriority; } - - double currentAge() const; - double freshnessLifetime() const; - - RefPtr<CachedMetadata> m_cachedMetadata; - - double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache - - unsigned m_encodedSize; - unsigned m_decodedSize; - unsigned m_accessCount; - unsigned m_handleCount; - unsigned m_preloadCount; - - unsigned m_preloadResult : 2; // PreloadResult - - bool m_inLiveDecodedResourcesList : 1; - bool m_requestedFromNetworkingLayer : 1; - bool m_sendResourceLoadCallbacks : 1; - - bool m_inCache : 1; - bool m_loading : 1; - - unsigned m_type : 3; // Type - unsigned m_status : 3; // Status - -#ifndef NDEBUG - bool m_deleted; - unsigned m_lruIndex; -#endif - - CachedResource* m_nextInAllResourcesList; - CachedResource* m_prevInAllResourcesList; - - CachedResource* m_nextInLiveResourcesList; - CachedResource* m_prevInLiveResourcesList; - - CachedResourceLoader* m_cachedResourceLoader; // only non-0 for resources that are not in the cache - - // 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; - - // If this field is non-null, the resource has a proxy for checking whether it is still up to date (see m_resourceToRevalidate). - CachedResource* m_proxyResource; - - // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. - HashSet<CachedResourceHandleBase*> m_handlesToRevalidate; -}; - -} - -#endif diff --git a/WebCore/loader/cache/CachedResourceClient.h b/WebCore/loader/cache/CachedResourceClient.h deleted file mode 100644 index 275d331..0000000 --- a/WebCore/loader/cache/CachedResourceClient.h +++ /dev/null @@ -1,71 +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, 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 CachedResourceClient_h -#define CachedResourceClient_h - -#include <wtf/FastAllocBase.h> -#include <wtf/Forward.h> - -namespace WebCore { - - class CachedCSSStyleSheet; - class CachedFont; - class CachedResource; - class CachedImage; - class Image; - class IntRect; - class KURL; - - /** - * @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 FastAllocBase - { - 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. If not null, the IntRect is the changed rect of the image. - virtual void imageChanged(CachedImage*, const IntRect* = 0) { }; - - // 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& /* href */, const KURL& /* baseURL */, const String& /* charset */, const CachedCSSStyleSheet*) { } - virtual void setXSLStyleSheet(const String& /* href */, const KURL& /* baseURL */, const String& /* sheet */) { } - virtual void fontLoaded(CachedFont*) {}; - virtual void notifyFinished(CachedResource*) { } - }; - -} - -#endif diff --git a/WebCore/loader/cache/CachedResourceClientWalker.cpp b/WebCore/loader/cache/CachedResourceClientWalker.cpp deleted file mode 100644 index 142a2a1..0000000 --- a/WebCore/loader/cache/CachedResourceClientWalker.cpp +++ /dev/null @@ -1,53 +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 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 "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/cache/CachedResourceClientWalker.h b/WebCore/loader/cache/CachedResourceClientWalker.h deleted file mode 100644 index d079584..0000000 --- a/WebCore/loader/cache/CachedResourceClientWalker.h +++ /dev/null @@ -1,49 +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, 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. - - 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/cache/CachedResourceHandle.cpp b/WebCore/loader/cache/CachedResourceHandle.cpp deleted file mode 100644 index 871292c..0000000 --- a/WebCore/loader/cache/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/cache/CachedResourceHandle.h b/WebCore/loader/cache/CachedResourceHandle.h deleted file mode 100644 index 7d485bf..0000000 --- a/WebCore/loader/cache/CachedResourceHandle.h +++ /dev/null @@ -1,104 +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. - // Parenthesis is needed for winscw compiler to resolve class qualifier in this case. - 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); - 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(); } - }; - - // Don't inline for winscw compiler to prevent the compiler aggressively resolving - // the base class of R* when CachedResourceHandler<T>(R*) is inlined. The bug is - // reported at: https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812. - template <class R> -#if !COMPILER(WINSCW) - inline -#endif - CachedResourceHandle<R>::CachedResourceHandle(R* res) : CachedResourceHandleBase(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; - } - 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/cache/CachedResourceLoader.cpp b/WebCore/loader/cache/CachedResourceLoader.cpp deleted file mode 100644 index 60f9810..0000000 --- a/WebCore/loader/cache/CachedResourceLoader.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) - Copyright (C) 2001 Dirk Mueller (mueller@kde.org) - Copyright (C) 2002 Waldo Bastian (bastian@kde.org) - Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. - Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - This class provides all functionality needed for loading images, style sheets and html - pages from the web. It has a memory cache for these objects. -*/ - -#include "config.h" -#include "CachedResourceLoader.h" - -#include "CachedCSSStyleSheet.h" -#include "CachedFont.h" -#include "CachedImage.h" -#include "CachedScript.h" -#include "CachedXSLStyleSheet.h" -#include "Console.h" -#include "DOMWindow.h" -#include "Document.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "HTMLElement.h" -#include "MemoryCache.h" -#include "PingLoader.h" -#include "SecurityOrigin.h" -#include "Settings.h" -#include <wtf/text/StringConcatenate.h> - -#define PRELOAD_DEBUG 0 - -namespace WebCore { - -CachedResourceLoader::CachedResourceLoader(Document* document) - : m_cache(cache()) - , m_document(document) - , m_requestCount(0) -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - , m_blockNetworkImage(false) -#endif - , m_autoLoadImages(true) - , m_loadFinishing(false) - , m_allowStaleResources(false) -{ - m_cache->addCachedResourceLoader(this); -} - -CachedResourceLoader::~CachedResourceLoader() -{ - cancelRequests(); - clearPreloads(); - DocumentResourceMap::iterator end = m_documentResources.end(); - for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) - it->second->setCachedResourceLoader(0); - m_cache->removeCachedResourceLoader(this); - - // Make sure no requests still point to this CachedResourceLoader - ASSERT(m_requestCount == 0); -} - -CachedResource* CachedResourceLoader::cachedResource(const String& resourceURL) const -{ - KURL url = m_document->completeURL(resourceURL); - return cachedResource(url); -} - -CachedResource* CachedResourceLoader::cachedResource(const KURL& resourceURL) const -{ - KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL); - return m_documentResources.get(url).get(); -} - -Frame* CachedResourceLoader::frame() const -{ - return m_document->frame(); -} - -void CachedResourceLoader::checkForReload(const KURL& fullURL) -{ - if (m_allowStaleResources) - return; // Don't reload resources while pasting - - if (fullURL.isEmpty()) - return; - - if (m_reloadedURLs.contains(fullURL.string())) - return; - - CachedResource* existing = cache()->resourceForURL(fullURL); - if (!existing || existing->isPreloaded()) - return; - - switch (cachePolicy()) { - case CachePolicyVerify: - if (!existing->mustRevalidate(CachePolicyVerify)) - return; - cache()->revalidateResource(existing, this); - break; - case CachePolicyCache: - if (!existing->mustRevalidate(CachePolicyCache)) - return; - cache()->revalidateResource(existing, this); - break; - case CachePolicyReload: - cache()->remove(existing); - break; - case CachePolicyRevalidate: - cache()->revalidateResource(existing, this); - break; - case CachePolicyHistoryBuffer: - return; - } - - m_reloadedURLs.add(fullURL.string()); -} - -CachedImage* CachedResourceLoader::requestImage(const String& url) -{ - if (Frame* f = frame()) { - Settings* settings = f->settings(); - if (!f->loader()->client()->allowImages(!settings || settings->areImagesEnabled())) - return 0; - - if (f->loader()->pageDismissalEventBeingDispatched()) { - KURL completeURL = m_document->completeURL(url); - if (completeURL.isValid() && canRequest(CachedResource::ImageResource, completeURL)) - PingLoader::loadImage(f, completeURL); - return 0; - } - } - CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url, String())); - if (autoLoadImages() && resource && resource->stillNeedsLoad()) { -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (shouldBlockNetworkImage(url)) { - return resource; - } -#endif - resource->setLoading(true); - load(resource, true); - } - return resource; -} - -CachedFont* CachedResourceLoader::requestFont(const String& url) -{ - return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, url, String())); -} - -CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority) -{ - return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, charset, priority)); -} - -CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(const String& url, const String& charset) -{ - return cache()->requestUserCSSStyleSheet(this, KURL(KURL(), url), charset); -} - -CachedScript* CachedResourceLoader::requestScript(const String& url, const String& charset) -{ - return static_cast<CachedScript*>(requestResource(CachedResource::Script, url, charset)); -} - -#if ENABLE(XSLT) -CachedXSLStyleSheet* CachedResourceLoader::requestXSLStyleSheet(const String& url) -{ - return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XSLStyleSheet, url, String())); -} -#endif - -#if ENABLE(LINK_PREFETCH) -CachedResource* CachedResourceLoader::requestLinkPrefetch(const String& url) -{ - ASSERT(frame()); - return requestResource(CachedResource::LinkPrefetch, url, String()); -} -#endif - -bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url) -{ - // Some types of resources can be loaded only from the same origin. Other - // types of resources, like Images, Scripts, and CSS, can be loaded from - // any URL. - switch (type) { - case CachedResource::ImageResource: - case CachedResource::CSSStyleSheet: - case CachedResource::Script: - case CachedResource::FontResource: -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: -#endif - // These types of resources can be loaded from any origin. - // FIXME: Are we sure about CachedResource::FontResource? - break; -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: - if (!m_document->securityOrigin()->canRequest(url)) { - printAccessDeniedMessage(url); - return false; - } - break; -#endif - default: - ASSERT_NOT_REACHED(); - break; - } - - // Given that the load is allowed by the same-origin policy, we should - // check whether the load passes the mixed-content policy. - // - // Note: Currently, we always allow mixed content, but we generate a - // callback to the FrameLoaderClient in case the embedder wants to - // update any security indicators. - // - switch (type) { - case CachedResource::Script: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif - // These resource can inject script into the current document. - if (Frame* f = frame()) - f->loader()->checkIfRunInsecureContent(m_document->securityOrigin(), url); - break; - case CachedResource::ImageResource: - case CachedResource::CSSStyleSheet: - case CachedResource::FontResource: { - // These resources can corrupt only the frame's pixels. - if (Frame* f = frame()) { - Frame* top = f->tree()->top(); - top->loader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), url); - } - break; - } -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: - // Prefetch cannot affect the current document. - break; -#endif - default: - ASSERT_NOT_REACHED(); - break; - } - // FIXME: Consider letting the embedder block mixed content loads. - return true; -} - -CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, const String& url, const String& charset, ResourceLoadPriority priority, bool isPreload) -{ - KURL fullURL = m_document->completeURL(url); - - // If only the fragment identifiers differ, it is the same resource. - fullURL = MemoryCache::removeFragmentIdentifierIfNeeded(fullURL); - - if (!fullURL.isValid() || !canRequest(type, fullURL)) - return 0; - - if (cache()->disabled()) { - DocumentResourceMap::iterator it = m_documentResources.find(fullURL.string()); - - if (it != m_documentResources.end()) { - it->second->setCachedResourceLoader(0); - m_documentResources.remove(it); - } - } - - checkForReload(fullURL); - - bool allowForHistoryOnlyResources = cachePolicy() == CachePolicyHistoryBuffer; - CachedResource* resource = cache()->requestResource(this, type, fullURL, charset, priority, isPreload, allowForHistoryOnlyResources); - if (resource) { - // Check final URL of resource to catch redirects. - // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. - if (fullURL != resource->url() && !canRequest(type, KURL(ParsedURLString, resource->url()))) - return 0; - - m_documentResources.set(resource->url(), resource); - checkCacheObjectStatus(resource); - } - return resource; -} - -void CachedResourceLoader::printAccessDeniedMessage(const KURL& url) const -{ - if (url.isNull()) - return; - - if (!frame()) - return; - - Settings* settings = frame()->settings(); - if (!settings || settings->privateBrowsingEnabled()) - return; - - String message = m_document->url().isNull() ? - makeString("Unsafe attempt to load URL ", url.string(), '.') : - makeString("Unsafe attempt to load URL ", url.string(), " from frame with URL ", m_document->url().string(), ". Domains, protocols and ports must match.\n"); - - // FIXME: provide a real line number and source URL. - frame()->domWindow()->console()->addMessage(OtherMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String()); -} - -void CachedResourceLoader::setAutoLoadImages(bool enable) -{ - if (enable == m_autoLoadImages) - return; - - m_autoLoadImages = enable; - - if (!m_autoLoadImages) - return; - - DocumentResourceMap::iterator end = m_documentResources.end(); - for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) { - CachedResource* resource = it->second.get(); - if (resource->type() == CachedResource::ImageResource) { - CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource)); -#ifdef ANDROID_BLOCK_NETWORK_IMAGE - if (shouldBlockNetworkImage(image->url())) - continue; -#endif - - if (image->stillNeedsLoad()) - load(image, true); - } - } -} - -#ifdef ANDROID_BLOCK_NETWORK_IMAGE -bool CachedResourceLoader::shouldBlockNetworkImage(const String& url) const -{ - if (!m_blockNetworkImage) - return false; - - KURL kurl = m_document->completeURL(url); - if (kurl.protocolIs("http") || kurl.protocolIs("https")) - return true; - - return false; -} - -void CachedResourceLoader::setBlockNetworkImage(bool block) -{ - if (block == m_blockNetworkImage) - return; - - m_blockNetworkImage = block; - - if (!m_autoLoadImages || m_blockNetworkImage) - return; - - DocumentResourceMap::iterator end = m_documentResources.end(); - for (DocumentResourceMap::iterator it = m_documentResources.begin(); it != end; ++it) { - CachedResource* resource = it->second.get(); - if (resource->type() == CachedResource::ImageResource) { - CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage*>(resource)); - if (image->stillNeedsLoad()) - load(image, true); - } - } -} -#endif - -CachePolicy CachedResourceLoader::cachePolicy() const -{ - return frame() ? frame()->loader()->subresourceCachePolicy() : CachePolicyVerify; -} - -void CachedResourceLoader::removeCachedResource(CachedResource* resource) const -{ -#ifndef NDEBUG - DocumentResourceMap::iterator it = m_documentResources.find(resource->url()); - if (it != m_documentResources.end()) - ASSERT(it->second.get() == resource); -#endif - m_documentResources.remove(resource->url()); -} - -void CachedResourceLoader::load(CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) -{ - incrementRequestCount(resource); - - RefPtr<CachedResourceRequest> request = CachedResourceRequest::load(this, resource, incremental, securityCheck, sendResourceLoadCallbacks); - if (request) - m_requests.add(request); -} - -void CachedResourceLoader::loadDone(CachedResourceRequest* request) -{ - m_loadFinishing = false; - RefPtr<CachedResourceRequest> protect(request); - if (request) - m_requests.remove(request); - if (frame()) - frame()->loader()->loadDone(); - checkForPendingPreloads(); -} - -void CachedResourceLoader::cancelRequests() -{ - clearPendingPreloads(); - Vector<CachedResourceRequest*, 256> requestsToCancel; - RequestSet::iterator end = m_requests.end(); - for (RequestSet::iterator i = m_requests.begin(); i != end; ++i) - requestsToCancel.append((*i).get()); - - for (unsigned i = 0; i < requestsToCancel.size(); ++i) - requestsToCancel[i]->didFail(true); -} - -void CachedResourceLoader::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() || resource->status() != CachedResource::Cached) - 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 CachedResourceLoader::incrementRequestCount(const CachedResource* res) -{ - if (res->isPrefetch()) - return; - - ++m_requestCount; -} - -void CachedResourceLoader::decrementRequestCount(const CachedResource* res) -{ - if (res->isPrefetch()) - return; - - --m_requestCount; - ASSERT(m_requestCount > -1); -} - -int CachedResourceLoader::requestCount() -{ - if (m_loadFinishing) - return m_requestCount + 1; - return m_requestCount; -} - -void CachedResourceLoader::preload(CachedResource::Type type, const String& url, const String& charset, bool referencedFromBody) -{ - bool hasRendering = m_document->body() && m_document->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 CachedResourceLoader::checkForPendingPreloads() -{ - unsigned count = m_pendingPreloads.size(); - if (!count || !m_document->body() || !m_document->body()->renderer()) - return; - for (unsigned i = 0; i < count; ++i) { - PendingPreload& preload = m_pendingPreloads[i]; - // Don't request preload if the resource already loaded normally (this will result in double load if the page is being reloaded with cached results ignored). - if (!cachedResource(m_document->completeURL(preload.m_url))) - requestPreload(preload.m_type, preload.m_url, preload.m_charset); - } - m_pendingPreloads.clear(); -} - -void CachedResourceLoader::requestPreload(CachedResource::Type type, const String& url, const String& charset) -{ - String encoding; - if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet) - encoding = charset.isEmpty() ? m_document->frame()->loader()->writer()->encoding() : charset; - - CachedResource* resource = requestResource(type, url, encoding, ResourceLoadPriorityUnresolved, true); - if (!resource || (m_preloads && m_preloads->contains(resource))) - return; - resource->increasePreloadCount(); - - if (!m_preloads) - m_preloads = adoptPtr(new ListHashSet<CachedResource*>); - m_preloads->add(resource); - -#if PRELOAD_DEBUG - printf("PRELOADING %s\n", resource->url().latin1().data()); -#endif -} - -void CachedResourceLoader::clearPreloads() -{ -#if PRELOAD_DEBUG - printPreloadStats(); -#endif - if (!m_preloads) - return; - - ListHashSet<CachedResource*>::iterator end = m_preloads->end(); - for (ListHashSet<CachedResource*>::iterator it = m_preloads->begin(); it != end; ++it) { - CachedResource* res = *it; - res->decreasePreloadCount(); - if (res->canDelete() && !res->inCache()) - delete res; - else if (res->preloadResult() == CachedResource::PreloadNotReferenced) - cache()->remove(res); - } - m_preloads.clear(); -} - -void CachedResourceLoader::clearPendingPreloads() -{ - m_pendingPreloads.clear(); -} - -#if PRELOAD_DEBUG -void CachedResourceLoader::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/cache/CachedResourceLoader.h b/WebCore/loader/cache/CachedResourceLoader.h deleted file mode 100644 index a03e999..0000000 --- a/WebCore/loader/cache/CachedResourceLoader.h +++ /dev/null @@ -1,152 +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. - Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - This class provides all functionality needed for loading images, style sheets and html - pages from the web. It has a memory cache for these objects. -*/ - -#ifndef CachedResourceLoader_h -#define CachedResourceLoader_h - -#include "CachedResource.h" -#include "CachedResourceHandle.h" -#include "CachedResourceRequest.h" -#include "CachePolicy.h" -#include "ResourceLoadPriority.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/ListHashSet.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class CachedCSSStyleSheet; -class CachedFont; -class CachedImage; -class CachedScript; -class CachedXSLStyleSheet; -class Document; -class Frame; -class ImageLoader; -class KURL; - -// The CachedResourceLoader manages the loading of scripts/images/stylesheets for a single document. -class CachedResourceLoader : public Noncopyable { -friend class MemoryCache; -friend class ImageLoader; - -public: - CachedResourceLoader(Document*); - ~CachedResourceLoader(); - - CachedImage* requestImage(const String& url); - CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved); - 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(LINK_PREFETCH) - CachedResource* requestLinkPrefetch(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; - CachedResource* cachedResource(const KURL& url) const; - - typedef HashMap<String, CachedResourceHandle<CachedResource> > DocumentResourceMap; - const DocumentResourceMap& allCachedResources() const { return m_documentResources; } - - 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; - - Frame* frame() const; // Can be NULL - Document* document() const { return m_document; } - - void removeCachedResource(CachedResource*) const; - - void load(CachedResource*, bool incremental = false, SecurityCheckPolicy = DoSecurityCheck, bool sendResourceLoadCallbacks = true); - void loadFinishing() { m_loadFinishing = true; } - void loadDone(CachedResourceRequest*); - void cancelRequests(); - - void setAllowStaleResources(bool allowStaleResources) { m_allowStaleResources = allowStaleResources; } - - void incrementRequestCount(const CachedResource*); - void decrementRequestCount(const CachedResource*); - int requestCount(); - - void clearPreloads(); - void clearPendingPreloads(); - 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, ResourceLoadPriority priority = ResourceLoadPriorityUnresolved, 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&); - - MemoryCache* m_cache; - HashSet<String> m_reloadedURLs; - mutable DocumentResourceMap m_documentResources; - Document* m_document; - - typedef HashSet<RefPtr<CachedResourceRequest> > RequestSet; - RequestSet m_requests; - - int m_requestCount; - - OwnPtr<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_loadFinishing : 1; - bool m_allowStaleResources : 1; -}; - -} - -#endif diff --git a/WebCore/loader/cache/CachedResourceRequest.cpp b/WebCore/loader/cache/CachedResourceRequest.cpp deleted file mode 100644 index 827bb8e..0000000 --- a/WebCore/loader/cache/CachedResourceRequest.cpp +++ /dev/null @@ -1,280 +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 "CachedResourceRequest.h" - -#include "MemoryCache.h" -#include "CachedImage.h" -#include "CachedResource.h" -#include "CachedResourceLoader.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "Logging.h" -#include "ResourceHandle.h" -#include "ResourceLoadScheduler.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -#include "SharedBuffer.h" -#include <wtf/Assertions.h> -#include <wtf/Vector.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -static ResourceRequest::TargetType cachedResourceTypeToTargetType(CachedResource::Type type) -{ - switch (type) { - case CachedResource::CSSStyleSheet: -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: -#endif - return ResourceRequest::TargetIsStyleSheet; - case CachedResource::Script: - return ResourceRequest::TargetIsScript; - case CachedResource::FontResource: - return ResourceRequest::TargetIsFontResource; - case CachedResource::ImageResource: - return ResourceRequest::TargetIsImage; -#if ENABLE(LINK_PREFETCH) - case CachedResource::LinkPrefetch: - return ResourceRequest::TargetIsPrefetch; -#endif - } - ASSERT_NOT_REACHED(); - return ResourceRequest::TargetIsSubresource; -} - -CachedResourceRequest::CachedResourceRequest(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental) - : m_cachedResourceLoader(cachedResourceLoader) - , m_resource(resource) - , m_incremental(incremental) - , m_multipart(false) - , m_finishing(false) -{ - m_resource->setRequest(this); -} - -CachedResourceRequest::~CachedResourceRequest() -{ - m_resource->setRequest(0); -} - -PassRefPtr<CachedResourceRequest> CachedResourceRequest::load(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, bool incremental, SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks) -{ - RefPtr<CachedResourceRequest> request = adoptRef(new CachedResourceRequest(cachedResourceLoader, resource, incremental)); - - ResourceRequest resourceRequest(resource->url()); - resourceRequest.setTargetType(cachedResourceTypeToTargetType(resource->type())); - - if (!resource->accept().isEmpty()) - resourceRequest.setHTTPAccept(resource->accept()); - - if (resource->isCacheValidator()) { - CachedResource* resourceToRevalidate = resource->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()) { - ASSERT(cachedResourceLoader->cachePolicy() != CachePolicyReload); - if (cachedResourceLoader->cachePolicy() == CachePolicyRevalidate) - 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); - } - } - -#if ENABLE(LINK_PREFETCH) - if (resource->type() == CachedResource::LinkPrefetch) - resourceRequest.setHTTPHeaderField("Purpose", "prefetch"); -#endif - - ResourceLoadPriority priority = resource->loadPriority(); - - RefPtr<SubresourceLoader> loader = resourceLoadScheduler()->scheduleSubresourceLoad(cachedResourceLoader->document()->frame(), - request.get(), resourceRequest, priority, securityCheck, sendResourceLoadCallbacks); - if (!loader || loader->reachedTerminalState()) { - // FIXME: What if resources in other frames were waiting for this revalidation? - LOG(ResourceLoading, "Cannot start loading '%s'", resource->url().latin1().data()); - cachedResourceLoader->decrementRequestCount(resource); - cachedResourceLoader->loadFinishing(); - if (resource->resourceToRevalidate()) - cache()->revalidationFailed(resource); - resource->error(CachedResource::LoadError); - cachedResourceLoader->loadDone(0); - return 0; - } - request->m_loader = loader; - return request.release(); -} - -void CachedResourceRequest::willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse&) -{ - m_resource->setRequestedFromNetworkingLayer(); -} - -void CachedResourceRequest::didFinishLoading(SubresourceLoader* loader) -{ - if (m_finishing) - return; - - ASSERT(loader == m_loader.get()); - ASSERT(!m_resource->resourceToRevalidate()); - LOG(ResourceLoading, "Received '%s'.", m_resource->url().latin1().data()); - - // Prevent the document from being destroyed before we are done with - // the cachedResourceLoader that it will delete when the document gets deleted. - RefPtr<Document> protector(m_cachedResourceLoader->document()); - if (!m_multipart) - m_cachedResourceLoader->decrementRequestCount(m_resource); - m_finishing = true; - - // 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 (!m_resource->errorOccurred()) { - m_cachedResourceLoader->loadFinishing(); - m_resource->data(loader->resourceData(), true); - if (!m_resource->errorOccurred()) - m_resource->finish(); - } - m_cachedResourceLoader->loadDone(this); -} - -void CachedResourceRequest::didFail(SubresourceLoader*, const ResourceError&) -{ - if (!m_loader) - return; - didFail(); -} - -void CachedResourceRequest::didFail(bool cancelled) -{ - if (m_finishing) - return; - - LOG(ResourceLoading, "Failed to load '%s' (cancelled=%d).\n", m_resource->url().latin1().data(), cancelled); - - // Prevent the document from being destroyed before we are done with - // the cachedResourceLoader that it will delete when the document gets deleted. - RefPtr<Document> protector(m_cachedResourceLoader->document()); - if (!m_multipart) - m_cachedResourceLoader->decrementRequestCount(m_resource); - m_finishing = true; - m_loader->clearClient(); - - if (m_resource->resourceToRevalidate()) - cache()->revalidationFailed(m_resource); - - if (!cancelled) { - m_cachedResourceLoader->loadFinishing(); - m_resource->error(CachedResource::LoadError); - } - - if (cancelled || !m_resource->isPreloaded()) - cache()->remove(m_resource); - - m_cachedResourceLoader->loadDone(this); -} - -void CachedResourceRequest::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response) -{ - ASSERT(loader == m_loader.get()); - if (m_resource->isCacheValidator()) { - if (response.httpStatusCode() == 304) { - // 304 Not modified / Use local copy - loader->clearClient(); - RefPtr<Document> protector(m_cachedResourceLoader->document()); - m_cachedResourceLoader->decrementRequestCount(m_resource); - m_finishing = true; - - // Existing resource is ok, just use it updating the expiration time. - cache()->revalidationSucceeded(m_resource, response); - - if (m_cachedResourceLoader->frame()) - m_cachedResourceLoader->frame()->loader()->checkCompleted(); - - m_cachedResourceLoader->loadDone(this); - return; - } - // Did not get 304 response, continue as a regular resource load. - cache()->revalidationFailed(m_resource); - } - - m_resource->setResponse(response); - - String encoding = response.textEncodingName(); - if (!encoding.isNull()) - m_resource->setEncoding(encoding); - - if (m_multipart) { - ASSERT(m_resource->isImage()); - static_cast<CachedImage*>(m_resource)->clear(); - if (m_cachedResourceLoader->frame()) - m_cachedResourceLoader->frame()->loader()->checkCompleted(); - } else if (response.isMultipart()) { - m_multipart = true; - - // We don't count multiParts in a CachedResourceLoader's request count - m_cachedResourceLoader->decrementRequestCount(m_resource); - - // If we get a multipart response, we must have a handle - ASSERT(loader->handle()); - if (!m_resource->isImage()) - loader->handle()->cancel(); - } -} - -void CachedResourceRequest::didReceiveData(SubresourceLoader* loader, const char* data, int size) -{ - ASSERT(loader == m_loader.get()); - ASSERT(!m_resource->isCacheValidator()); - - if (m_resource->errorOccurred()) - return; - - if (m_resource->response().httpStatusCode() >= 400) { - if (!m_resource->shouldIgnoreHTTPStatusCodeErrors()) - m_resource->error(CachedResource::LoadError); - return; - } - - // Set the data. - if (m_multipart) { - // 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); - m_resource->data(copiedData.release(), true); - } else if (m_incremental) - m_resource->data(loader->resourceData(), false); -} - -void CachedResourceRequest::didReceiveCachedMetadata(SubresourceLoader*, const char* data, int size) -{ - ASSERT(!m_resource->isCacheValidator()); - m_resource->setSerializedCachedMetadata(data, size); -} - -} //namespace WebCore diff --git a/WebCore/loader/cache/CachedResourceRequest.h b/WebCore/loader/cache/CachedResourceRequest.h deleted file mode 100644 index 389b9ce..0000000 --- a/WebCore/loader/cache/CachedResourceRequest.h +++ /dev/null @@ -1,65 +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 CachedResourceRequest_h -#define CachedResourceRequest_h - -#include "FrameLoaderTypes.h" -#include "SubresourceLoader.h" -#include "SubresourceLoaderClient.h" -#include <wtf/HashMap.h> -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - - class CachedResource; - class CachedResourceLoader; - class Request; - - class CachedResourceRequest : public RefCounted<CachedResourceRequest>, private SubresourceLoaderClient { - public: - static PassRefPtr<CachedResourceRequest> load(CachedResourceLoader*, CachedResource*, bool incremental, SecurityCheckPolicy, bool sendResourceLoadCallbacks); - ~CachedResourceRequest(); - void didFail(bool cancelled = false); - - CachedResourceLoader* cachedResourceLoader() const { return m_cachedResourceLoader; } - - private: - CachedResourceRequest(CachedResourceLoader*, CachedResource*, bool incremental); - virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse&); - virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&); - virtual void didReceiveData(SubresourceLoader*, const char*, int); - virtual void didReceiveCachedMetadata(SubresourceLoader*, const char*, int); - virtual void didFinishLoading(SubresourceLoader*); - virtual void didFail(SubresourceLoader*, const ResourceError&); - - RefPtr<SubresourceLoader> m_loader; - CachedResourceLoader* m_cachedResourceLoader; - CachedResource* m_resource; - bool m_incremental; - bool m_multipart; - bool m_finishing; - }; - -} - -#endif diff --git a/WebCore/loader/cache/CachedScript.cpp b/WebCore/loader/cache/CachedScript.cpp deleted file mode 100644 index 54b4503..0000000 --- a/WebCore/loader/cache/CachedScript.cpp +++ /dev/null @@ -1,124 +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. - - 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 "MemoryCache.h" -#include "CachedResourceClient.h" -#include "CachedResourceClientWalker.h" -#include "SharedBuffer.h" -#include "TextResourceDecoder.h" -#include <wtf/Vector.h> - -namespace WebCore { - -CachedScript::CachedScript(const String& url, const String& charset) - : CachedResource(url, Script) - , m_decoder(TextResourceDecoder::create("application/javascript", charset)) - , m_decodedDataDeletionTimer(this, &CachedScript::decodedDataDeletionTimerFired) -{ - // 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("*/*"); -} - -CachedScript::~CachedScript() -{ -} - -void CachedScript::allClientsRemoved() -{ - m_decodedDataDeletionTimer.startOneShot(0); -} - -void CachedScript::setEncoding(const String& chs) -{ - m_decoder->setEncoding(chs, TextResourceDecoder::EncodingFromHTTPHeader); -} - -String CachedScript::encoding() const -{ - return m_decoder->encoding().name(); -} - -const String& CachedScript::script() -{ - ASSERT(!isPurgeable()); - - if (!m_script && m_data) { - m_script = m_decoder->decode(m_data->data(), encodedSize()); - m_script += m_decoder->flush(); - setDecodedSize(m_script.length() * sizeof(UChar)); - } - m_decodedDataDeletionTimer.startOneShot(0); - return m_script; -} - -void CachedScript::data(PassRefPtr<SharedBuffer> data, bool allDataReceived) -{ - if (!allDataReceived) - return; - - m_data = data; - setEncodedSize(m_data.get() ? m_data->size() : 0); - setLoading(false); - checkNotify(); -} - -void CachedScript::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient* c = w.next()) - c->notifyFinished(this); -} - -void CachedScript::error(CachedResource::Status status) -{ - setStatus(status); - ASSERT(errorOccurred()); - setLoading(false); - checkNotify(); -} - -void CachedScript::destroyDecodedData() -{ - m_script = String(); - setDecodedSize(0); - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() && isSafeToMakePurgeable()) - makePurgeable(true); -} - -void CachedScript::decodedDataDeletionTimerFired(Timer<CachedScript>*) -{ - destroyDecodedData(); -} - -} // namespace WebCore diff --git a/WebCore/loader/cache/CachedScript.h b/WebCore/loader/cache/CachedScript.h deleted file mode 100644 index 30fcb1e..0000000 --- a/WebCore/loader/cache/CachedScript.h +++ /dev/null @@ -1,65 +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, 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 CachedScript_h -#define CachedScript_h - -#include "CachedResource.h" -#include "Timer.h" - -namespace WebCore { - - class CachedResourceLoader; - class TextResourceDecoder; - - class CachedScript : public CachedResource { - public: - CachedScript(const String& url, const String& charset); - virtual ~CachedScript(); - - const String& script(); - - virtual void allClientsRemoved(); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status); - - void checkNotify(); - - virtual void destroyDecodedData(); - - private: - void decodedDataDeletionTimerFired(Timer<CachedScript>*); - virtual PurgePriority purgePriority() const { return PurgeLast; } - - String m_script; - RefPtr<TextResourceDecoder> m_decoder; - Timer<CachedScript> m_decodedDataDeletionTimer; - }; -} - -#endif diff --git a/WebCore/loader/cache/CachedXSLStyleSheet.cpp b/WebCore/loader/cache/CachedXSLStyleSheet.cpp deleted file mode 100644 index ca7bf13..0000000 --- a/WebCore/loader/cache/CachedXSLStyleSheet.cpp +++ /dev/null @@ -1,100 +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. - - 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 "SharedBuffer.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::didAddClient(CachedResourceClient* c) -{ - if (!isLoading()) - c->setXSLStyleSheet(m_url, m_response.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(); - } - setLoading(false); - checkNotify(); -} - -void CachedXSLStyleSheet::checkNotify() -{ - if (isLoading()) - return; - - CachedResourceClientWalker w(m_clients); - while (CachedResourceClient *c = w.next()) - c->setXSLStyleSheet(m_url, m_response.url(), m_sheet); -} - -void CachedXSLStyleSheet::error(CachedResource::Status status) -{ - setStatus(status); - ASSERT(errorOccurred()); - setLoading(false); - checkNotify(); -} - -#endif - -} diff --git a/WebCore/loader/cache/CachedXSLStyleSheet.h b/WebCore/loader/cache/CachedXSLStyleSheet.h deleted file mode 100644 index 8b29792..0000000 --- a/WebCore/loader/cache/CachedXSLStyleSheet.h +++ /dev/null @@ -1,62 +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, 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 CachedXSLStyleSheet_h -#define CachedXSLStyleSheet_h - -#include "CachedResource.h" -#include <wtf/Vector.h> - -namespace WebCore { - - class CachedResourceLoader; - class TextResourceDecoder; - -#if ENABLE(XSLT) - class CachedXSLStyleSheet : public CachedResource { - public: - CachedXSLStyleSheet(const String& url); - - const String& sheet() const { return m_sheet; } - - virtual void didAddClient(CachedResourceClient*); - - virtual void setEncoding(const String&); - virtual String encoding() const; - virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived); - virtual void error(CachedResource::Status); - - void checkNotify(); - - protected: - String m_sheet; - RefPtr<TextResourceDecoder> m_decoder; - }; - -#endif - -} - -#endif diff --git a/WebCore/loader/cache/MemoryCache.cpp b/WebCore/loader/cache/MemoryCache.cpp deleted file mode 100644 index 8826cec..0000000 --- a/WebCore/loader/cache/MemoryCache.cpp +++ /dev/null @@ -1,829 +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 "MemoryCache.h" - -#include "CachedCSSStyleSheet.h" -#include "CachedFont.h" -#include "CachedImage.h" -#include "CachedScript.h" -#include "CachedXSLStyleSheet.h" -#include "CachedResourceLoader.h" -#include "Document.h" -#include "FrameLoader.h" -#include "FrameLoaderTypes.h" -#include "FrameView.h" -#include "Image.h" -#include "Logging.h" -#include "ResourceHandle.h" -#include "SecurityOrigin.h" -#include <stdio.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.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; - -MemoryCache* cache() -{ - static MemoryCache* staticCache = new MemoryCache; - return staticCache; -} - -MemoryCache::MemoryCache() - : 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(LINK_PREFETCH) - case CachedResource::LinkPrefetch: - return new CachedResource(url.string(), CachedResource::LinkPrefetch); -#endif - default: - break; - } - - return 0; -} - -CachedResource* MemoryCache::requestResource(CachedResourceLoader* cachedResourceLoader, CachedResource::Type type, const KURL& requestURL, const String& charset, ResourceLoadPriority priority, bool requestIsPreload, bool forHistory) -{ - LOG(ResourceLoading, "MemoryCache::requestResource '%s', charset '%s', priority=%d, preload=%u, forHistory=%u", requestURL.string().latin1().data(), charset.latin1().data(), priority, requestIsPreload, forHistory); - - // 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 (requestURL.isEmpty()) - return 0; - - // Ensure this is the pure primary resource URL. - KURL url = removeFragmentIdentifierIfNeeded(requestURL); - - // Look up the resource in our map. - CachedResource* resource = resourceForURL(url); - - // Non https "no-store" resources are left in the cache to be used for back/forward navigation only. - // If this is not a request forHistory and the resource was served with "no-store" we should evict - // it here and make a fresh request. - if (!forHistory && resource && resource->response().cacheControlContainsNoStore()) { - LOG(ResourceLoading, "MemoryCache::requestResource cleared a for history only resource due to a non-history request for the resource"); - evict(resource); - resource = 0; - } - - if (resource && requestIsPreload && !resource->isPreloaded()) { - LOG(ResourceLoading, "MemoryCache::requestResource already has a preload request for this request, and it hasn't been preloaded yet"); - return 0; - } - - if (!cachedResourceLoader->document()->securityOrigin()->canDisplay(url)) { - LOG(ResourceLoading, "...URL was not allowed by SecurityOrigin"); - if (!requestIsPreload) - FrameLoader::reportLocalLoadFailed(cachedResourceLoader->document()->frame(), url.string()); - return 0; - } - - if (resource && resource->type() != type) { - LOG(ResourceLoading, "Cache::requestResource found a cache resource with matching url but different type, evicting and loading with new type."); - evict(resource); - resource = 0; - } - - if (!resource) { - LOG(ResourceLoading, "CachedResource for '%s' wasn't found in cache. Creating it", url.string().latin1().data()); - // 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); - - // Default priority based on resource type is used if the request did not specify one. - if (priority != ResourceLoadPriorityUnresolved) - resource->setLoadPriority(priority); - - resource->load(cachedResourceLoader); - - 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. - resource->setInCache(false); - delete resource; - return 0; - } - - 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->setCachedResourceLoader(cachedResourceLoader); - } - } else { - // FIXME: Upgrading the priority doesn't really do much since the ResourceLoadScheduler does not currently - // allow changing priorities. This might become important if we make scheduling priorities - // more dynamic. - if (priority != ResourceLoadPriorityUnresolved && resource->loadPriority() < priority) - resource->setLoadPriority(priority); - } - - if (!disabled()) { - // This will move the resource to the front of its LRU list and increase its access count. - resourceAccessed(resource); - } - - LOG(ResourceLoading, "MemoryCache::requestResource for '%s' returning resource %p\n", url.string().latin1().data(), resource); - - return resource; -} - -CachedCSSStyleSheet* MemoryCache::requestUserCSSStyleSheet(CachedResourceLoader* cachedResourceLoader, const KURL& requestURL, const String& charset) -{ - // Ensure this is the pure primary resource URL. - KURL url = removeFragmentIdentifierIfNeeded(requestURL); - - CachedCSSStyleSheet* userSheet; - if (CachedResource* existing = resourceForURL(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(cachedResourceLoader, false, SkipSecurityCheck, 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; -} - -KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) -{ - if (!originalURL.hasFragmentIdentifier()) - return originalURL; - // Strip away fragment identifier from HTTP and file urls. - // Data urls must be unmodified and it is also safer to keep them for custom protocols. - if (!(originalURL.protocolInHTTPFamily() || originalURL.isLocalFile())) - return originalURL; - KURL url = originalURL; - url.removeFragmentIdentifier(); - return url; -} - -void MemoryCache::revalidateResource(CachedResource* resource, CachedResourceLoader* cachedResourceLoader) -{ - ASSERT(resource); - ASSERT(resource->inCache()); - ASSERT(resource == m_resources.get(resource->url())); - ASSERT(!disabled()); - if (resource->resourceToRevalidate()) - return; - if (!resource->canUseCacheValidator()) { - evict(resource); - return; - } - const String& url = resource->url(); - CachedResource* newResource = createResource(resource->type(), KURL(ParsedURLString, url), resource->encoding()); - LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource, resource); - newResource->setResourceToRevalidate(resource); - evict(resource); - m_resources.set(url, newResource); - newResource->setInCache(true); - resourceAccessed(newResource); - newResource->load(cachedResourceLoader); -} - -void MemoryCache::revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse& response) -{ - CachedResource* resource = revalidatingResource->resourceToRevalidate(); - ASSERT(resource); - ASSERT(!resource->inCache()); - ASSERT(resource->isLoaded()); - ASSERT(revalidatingResource->inCache()); - - evict(revalidatingResource); - - ASSERT(!m_resources.get(resource->url())); - m_resources.set(resource->url(), resource); - resource->setInCache(true); - resource->updateResponseAfterRevalidation(response); - 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 MemoryCache::revalidationFailed(CachedResource* revalidatingResource) -{ - LOG(ResourceLoading, "Revalidation failed for %p", revalidatingResource); - ASSERT(revalidatingResource->resourceToRevalidate()); - revalidatingResource->clearResourceToRevalidate(); -} - -CachedResource* MemoryCache::resourceForURL(const KURL& resourceURL) -{ - KURL url = removeFragmentIdentifierIfNeeded(resourceURL); - CachedResource* resource = m_resources.get(url); - bool wasPurgeable = MemoryCache::shouldMakeResourcePurgeableOnEviction() && resource && resource->isPurgeable(); - if (resource && !resource->makePurgeable(false)) { - ASSERT(!resource->hasClients()); - evict(resource); - return 0; - } - // Add the size back since we had subtracted it when we marked the memory as purgeable. - if (wasPurgeable) - adjustSize(resource->hasClients(), resource->size()); - return resource; -} - -unsigned MemoryCache::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 MemoryCache::liveCapacity() const -{ - // Live resource capacity is whatever is left over after calculating dead resource capacity. - return m_capacity - deadCapacity(); -} - -void MemoryCache::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 = WTF::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. - - // The list might not be sorted by the m_lastDecodedAccessTime. The impact - // of this weaker invariant is minor as the below if statement to check the - // elapsedTime will evaluate to false as the currentTime will be a lot - // greater than the current->m_lastDecodedAccessTime. - // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 - 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 different LRU - // list in m_allResources. - current->destroyDecodedData(); - - if (targetSize && m_liveSize <= targetSize) - return; - } - current = prev; - } -} - -void MemoryCache::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(); - - if (!m_inPruneDeadResources) { - // See if we have any purged resources we can evict. - for (int i = 0; i < size; i++) { - CachedResource* current = m_allResources[i].m_tail; - while (current) { - CachedResource* prev = current->m_prevInAllResourcesList; - if (current->wasPurged()) { - ASSERT(!current->hasClients()); - ASSERT(!current->isPreloaded()); - evict(current); - } - current = prev; - } - } - if (targetSize && m_deadSize <= targetSize) - return; - } - - 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()) { - // Destroy our decoded data. This will remove us from - // m_liveDecodedResources, and possibly move us to a different - // 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() && !current->isCacheValidator()) { - if (!makeResourcePurgeable(current)) - 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 MemoryCache::setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes) -{ - ASSERT(minDeadBytes <= maxDeadBytes); - ASSERT(maxDeadBytes <= totalBytes); - m_minDeadCapacity = minDeadBytes; - m_maxDeadCapacity = maxDeadBytes; - m_capacity = totalBytes; - prune(); -} - -bool MemoryCache::makeResourcePurgeable(CachedResource* resource) -{ - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction()) - return false; - - if (!resource->inCache()) - return false; - - if (resource->isPurgeable()) - return true; - - if (!resource->isSafeToMakePurgeable()) - return false; - - if (!resource->makePurgeable(true)) - return false; - - adjustSize(resource->hasClients(), -static_cast<int>(resource->size())); - - return true; -} - -void MemoryCache::evict(CachedResource* resource) -{ - LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resource, resource->url().latin1().data()); - // 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); - - // If the resource was purged, it means we had already decremented the size when we made the - // resource purgeable in makeResourcePurgeable(). So adjust the size if we are evicting a - // resource that was not marked as purgeable. - if (!MemoryCache::shouldMakeResourcePurgeableOnEviction() || !resource->isPurgeable()) - adjustSize(resource->hasClients(), -static_cast<int>(resource->size())); - } else - ASSERT(m_resources.get(resource->url()) != resource); - - if (resource->canDelete()) - delete resource; -} - -void MemoryCache::addCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) -{ - m_cachedResourceLoaders.add(cachedResourceLoader); -} - -void MemoryCache::removeCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) -{ - m_cachedResourceLoaders.remove(cachedResourceLoader); -} - -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; -} - -MemoryCache::LRUList* MemoryCache::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 MemoryCache::removeFromLRUList(CachedResource* resource) -{ - // If we've never been accessed, then we're brand new and not in any list. - if (resource->accessCount() == 0) - return; - -#if !ASSERT_DISABLED - unsigned oldListIndex = resource->m_lruIndex; -#endif - - LRUList* list = lruListFor(resource); - -#if !ASSERT_DISABLED - // 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 MemoryCache::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 MemoryCache::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); - - // If this is the first time the resource has been accessed, adjust the size of the cache to account for its initial size. - if (!resource->accessCount()) - adjustSize(resource->hasClients(), resource->size()); - - // Add to our access count. - resource->increaseAccessCount(); - - // Now insert into the new queue. - insertInLRUList(resource); -} - -void MemoryCache::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 MemoryCache::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 MemoryCache::addToLiveResourcesSize(CachedResource* resource) -{ - m_liveSize += resource->size(); - m_deadSize -= resource->size(); -} - -void MemoryCache::removeFromLiveResourcesSize(CachedResource* resource) -{ - m_liveSize -= resource->size(); - m_deadSize += resource->size(); -} - -void MemoryCache::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; - } -} - -void MemoryCache::TypeStatistic::addResource(CachedResource* o) -{ - bool purged = o->wasPurged(); - bool purgeable = o->isPurgeable() && !purged; - int pageSize = (o->encodedSize() + o->overheadSize() + 4095) & ~4095; - count++; - size += purged ? 0 : o->size(); - liveSize += o->hasClients() ? o->size() : 0; - decodedSize += o->decodedSize(); - purgeableSize += purgeable ? pageSize : 0; - purgedSize += purged ? pageSize : 0; -} - -MemoryCache::Statistics MemoryCache::getStatistics() -{ - Statistics stats; - CachedResourceMap::iterator e = m_resources.end(); - for (CachedResourceMap::iterator i = m_resources.begin(); i != e; ++i) { - CachedResource* resource = i->second; - switch (resource->type()) { - case CachedResource::ImageResource: - stats.images.addResource(resource); - break; - case CachedResource::CSSStyleSheet: - stats.cssStyleSheets.addResource(resource); - break; - case CachedResource::Script: - stats.scripts.addResource(resource); - break; -#if ENABLE(XSLT) - case CachedResource::XSLStyleSheet: - stats.xslStyleSheets.addResource(resource); - break; -#endif - case CachedResource::FontResource: - stats.fonts.addResource(resource); - break; - default: - break; - } - } - return stats; -} - -void MemoryCache::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 MemoryCache::dumpStats() -{ - Statistics s = getStatistics(); - printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "PurgeableSize", "PurgedSize"); - printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------"); - printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize); - printf("%-13s %13d %13d %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize, s.cssStyleSheets.purgeableSize, s.cssStyleSheets.purgedSize); -#if ENABLE(XSLT) - printf("%-13s %13d %13d %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize, s.xslStyleSheets.purgeableSize, s.xslStyleSheets.purgedSize); -#endif - printf("%-13s %13d %13d %13d %13d %13d %13d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize, s.scripts.purgeableSize, s.scripts.purgedSize); - printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize, s.fonts.purgeableSize, s.fonts.purgedSize); - printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------"); -} - -void MemoryCache::dumpLRULists(bool includeLive) const -{ - printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged):\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, %d, %d); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients(), current->isPurgeable(), current->wasPurged()); - - current = prev; - } - } -} -#endif - -} // namespace WebCore diff --git a/WebCore/loader/cache/MemoryCache.h b/WebCore/loader/cache/MemoryCache.h deleted file mode 100644 index 57fec04..0000000 --- a/WebCore/loader/cache/MemoryCache.h +++ /dev/null @@ -1,237 +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, 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 <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/Vector.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -class CachedCSSStyleSheet; -class CachedResource; -class CachedResourceLoader; -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) -// --|----------++++++++++| -// -------|-----+++++++++++++++| -// -------|-----+++++++++++++++|+++++ - -// The behavior of the cache changes in the following way if shouldMakeResourcePurgeableOnEviction -// returns true. -// -// 1. Dead resources in the cache are kept in non-purgeable memory. -// 2. When we prune dead resources, instead of freeing them, we mark their memory as purgeable and -// keep the resources until the kernel reclaims the purgeable memory. -// -// By leaving the in-cache dead resources in dirty resident memory, we decrease the likelihood of -// the kernel claiming that memory and forcing us to refetch the resource (for example when a user -// presses back). -// -// And by having an unbounded number of resource objects using purgeable memory, we can use as much -// memory as is available on the machine. The trade-off here is that the CachedResource object (and -// its member variables) are allocated in non-purgeable TC-malloc'd memory so we would see slightly -// more memory use due to this. - -class MemoryCache : public Noncopyable { -public: - friend MemoryCache* 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; - int purgeableSize; - int purgedSize; - TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0) { } - void addResource(CachedResource*); - }; - - struct Statistics { - TypeStatistic images; - TypeStatistic cssStyleSheets; - TypeStatistic scripts; -#if ENABLE(XSLT) - TypeStatistic xslStyleSheets; -#endif - TypeStatistic fonts; - }; - - // 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(CachedResourceLoader*, CachedResource::Type, const KURL& url, const String& charset, ResourceLoadPriority, bool isPreload = false, bool forHistory = false); - - CachedCSSStyleSheet* requestUserCSSStyleSheet(CachedResourceLoader*, const KURL& url, const String& charset); - - static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL); - - void revalidateResource(CachedResource*, CachedResourceLoader*); - 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 addCachedResourceLoader(CachedResourceLoader*); - void removeCachedResourceLoader(CachedResourceLoader*); - - CachedResource* resourceForURL(const KURL&); - - // 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*); - - static bool shouldMakeResourcePurgeableOnEviction(); - - // 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: - MemoryCache(); - ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons. - - LRUList* lruListFor(CachedResource*); - void resourceAccessed(CachedResource*); -#ifndef NDEBUG - void dumpStats(); - 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. - - bool makeResourcePurgeable(CachedResource*); - void evict(CachedResource*); - - // Member variables. - HashSet<CachedResourceLoader*> m_cachedResourceLoaders; - - 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" multiple 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; -}; - -inline bool MemoryCache::shouldMakeResourcePurgeableOnEviction() -{ -#if PLATFORM(IOS) - return true; -#else - return false; -#endif -} - -// Function to obtain the global cache. -MemoryCache* cache(); - -} - -#endif diff --git a/WebCore/loader/cf/ResourceLoaderCFNet.cpp b/WebCore/loader/cf/ResourceLoaderCFNet.cpp deleted file mode 100644 index 83642c6..0000000 --- a/WebCore/loader/cf/ResourceLoaderCFNet.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2009 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 "ResourceLoader.h" - -#include "FrameLoader.h" -#include "FrameLoaderClient.h" - -namespace WebCore { - -bool ResourceLoader::shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef cachedResponse) -{ - if (!m_sendResourceLoadCallbacks) - return 0; - - CFURLResponseRef response = CFCachedURLResponseGetWrappedResponse(cachedResponse); - CFDataRef data = CFCachedURLResponseGetReceiverData(cachedResponse); - return frameLoader()->client()->shouldCacheResponse(documentLoader(), identifier(), response, CFDataGetBytePtr(data), CFDataGetLength(data)); -} - -} // namespace WebCore diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp deleted file mode 100644 index 6040037..0000000 --- a/WebCore/loader/icon/IconDatabase.cpp +++ /dev/null @@ -1,2096 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 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" - -#if ENABLE(ICONDATABASE) - -#include "AutodrainedPool.h" -#include "DocumentLoader.h" -#include "FileSystem.h" -#include "IconDatabaseClient.h" -#include "IconRecord.h" -#include "IntSize.h" -#include "Logging.h" -#include "ScriptController.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" -#include "SuddenTermination.h" -#include <wtf/CurrentTime.h> -#include <wtf/MainThread.h> -#include <wtf/StdLibExtras.h> -#include <wtf/text/CString.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) || PLATFORM(GTK) -#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" -static const int currentDatabaseVersion = 6; - -// Icons expire once every 4 days -static const int iconExpirationTime = 60*60*24*4; - -static 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) { - ScriptController::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.crossThreadString(); - - // 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_syncThreadRunning = m_syncThread; - 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; - - m_syncDB.close(); - ASSERT(!isOpen()); -} - -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.crossThreadString(); - 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.crossThreadString(); - - 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.crossThreadString()); - - // 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().threadsafeCopy() : 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 }; - - DEFINE_STATIC_LOCAL(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.crossThreadString(); - - record = new PageURLRecord(pageURL); - m_pageURLToRecordMap.set(pageURL, record); - } - - if (!record->retain()) { - if (pageURL.isNull()) - pageURL = pageURLOriginal.crossThreadString(); - - // 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.crossThreadString(), 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.crossThreadString(); - - 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.crossThreadString(); - iconURL = iconURLOriginal.crossThreadString(); - - 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_syncTimer(this, &IconDatabase::syncTimerFired) - , m_syncThreadRunning(false) - , m_isEnabled(false) - , m_privateBrowsingEnabled(false) - , m_threadTerminationRequested(false) - , m_removeIconsRequested(false) - , m_iconURLImportComplete(false) - , m_disabledSuddenTerminationForSyncThread(false) - , m_initialPruningComplete(false) - , m_client(defaultClient()) - , m_imported(false) - , m_isImportedSet(false) -{ - ASSERT(isMainThread()); -} - -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); - - if (!m_disabledSuddenTerminationForSyncThread) { - m_disabledSuddenTerminationForSyncThread = true; - // The following is balanced by the call to enableSuddenTermination in the - // syncThreadMainLoop function. - // FIXME: It would be better to only disable sudden termination if we have - // something to write, not just if we have something to read. - disableSuddenTermination(); - } - - m_syncCondition.signal(); -} - -void IconDatabase::scheduleOrDeferSyncTimer() -{ - ASSERT_NOT_SYNC_THREAD(); - - if (!m_syncTimer.isActive()) { - // The following is balanced by the call to enableSuddenTermination in the - // syncTimerFired function. - disableSuddenTermination(); - } - - m_syncTimer.startOneShot(updateTimerDelay); -} - -void IconDatabase::syncTimerFired(Timer<IconDatabase>*) -{ - ASSERT_NOT_SYNC_THREAD(); - wakeSyncThread(); - - // The following is balanced by the call to disableSuddenTermination in the - // scheduleOrDeferSyncTimer function. - enableSuddenTermination(); -} - -// ****************** -// *** 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.threadsafeCopy(); -} - -String IconDatabase::defaultDatabaseFilename() -{ - DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("WebpageIcons.db")); - return defaultDatabaseFilename.threadsafeCopy(); -} - -// 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 %lu interested page URLs that their icon URL is known due to the import", static_cast<unsigned long>(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(); - - bool shouldReenableSuddenTermination = 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 - static bool prunedUnretainedIcons = false; - 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; - - if (shouldReenableSuddenTermination) { - // The following is balanced by the call to disableSuddenTermination in the - // wakeSyncThread function. Any time we wait on the condition, we also have - // to enableSuddenTermation, after doing the next batch of work. - ASSERT(m_disabledSuddenTerminationForSyncThread); - enableSuddenTermination(); - m_disabledSuddenTerminationForSyncThread = false; - } - - m_syncCondition.wait(m_syncLock); - - shouldReenableSuddenTermination = true; - } - - m_syncLock.unlock(); - - // Thread is terminating at this point - cleanupSyncThread(); - - if (shouldReenableSuddenTermination) { - // The following is balanced by the call to disableSuddenTermination in the - // wakeSyncThread function. Any time we wait on the condition, we also have - // to enableSuddenTermation, after doing the next batch of work. - ASSERT(m_disabledSuddenTerminationForSyncThread); - enableSuddenTermination(); - m_disabledSuddenTerminationForSyncThread = false; - } - - return 0; -} - -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) { -#if OS(WINDOWS) - LOG(IconDatabase, "Pruning page with rowid %I64i from disk", static_cast<long long>(pageIDsToDelete[i])); -#else - LOG(IconDatabase, "Pruning page with rowid %lli from disk", static_cast<long long>(pageIDsToDelete[i])); -#endif - pageDeleteSQL.bindInt64(1, pageIDsToDelete[i]); - int result = pageDeleteSQL.step(); - if (result != SQLResultDone) -#if OS(WINDOWS) - LOG_ERROR("Unabled to delete page with id %I64i from disk", static_cast<long long>(pageIDsToDelete[i])); -#else - LOG_ERROR("Unabled to delete page with id %lli from disk", static_cast<long long>(pageIDsToDelete[i])); -#endif - 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.clear(); - m_removePageURLStatement.clear(); - m_getIconIDForIconURLStatement.clear(); - m_getImageDataForIconURLStatement.clear(); - m_addIconToIconInfoStatement.clear(); - m_addIconToIconDataStatement.clear(); - m_getImageDataStatement.clear(); - m_deletePageURLsForIconURLStatement.clear(); - m_deleteIconFromIconInfoStatement.clear(); - m_deleteIconFromIconDataStatement.clear(); - m_updateIconInfoStatement.clear(); - m_updateIconDataStatement.clear(); - m_setIconInfoStatement.clear(); - m_setIconDataStatement.clear(); -} - -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 = adoptPtr(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 - -#endif // ENABLE(ICONDATABASE) diff --git a/WebCore/loader/icon/IconDatabase.h b/WebCore/loader/icon/IconDatabase.h deleted file mode 100644 index 6146aa6..0000000 --- a/WebCore/loader/icon/IconDatabase.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 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 - -#include "Timer.h" -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> -#include <wtf/text/StringHash.h> - -#if ENABLE(ICONDATABASE) -#include "SQLiteDatabase.h" -#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 : public 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(); - void syncTimerFired(Timer<IconDatabase>*); - - Timer<IconDatabase> m_syncTimer; - 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; - bool m_disabledSuddenTerminationForSyncThread; - - 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; -#endif // ENABLE(ICONDATABASE) - -// *** 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; - -#if ENABLE(ICONDATABASE) -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 // IconDatabase_h diff --git a/WebCore/loader/icon/IconDatabaseClient.h b/WebCore/loader/icon/IconDatabaseClient.h deleted file mode 100644 index c210d7d..0000000 --- a/WebCore/loader/icon/IconDatabaseClient.h +++ /dev/null @@ -1,50 +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 - -#include <wtf/Forward.h> -#include <wtf/Noncopyable.h> - -// All of these client methods will be called from a non-main thread -// Take appropriate measures - -namespace WebCore { - -class IconDatabaseClient : public Noncopyable { -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 7b7cc9f..0000000 --- a/WebCore/loader/icon/IconDatabaseNone.cpp +++ /dev/null @@ -1,218 +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" - -#if !ENABLE(ICONDATABASE) - -#include "PlatformString.h" -#include "SharedBuffer.h" -#include <wtf/StdLibExtras.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() -{ - DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("Icons.db")); - return defaultDatabaseFilename.threadsafeCopy(); -} - -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() -{ -} - -size_t IconDatabase::pageURLMappingCount() -{ - return 0; -} - -size_t IconDatabase::retainedPageURLCount() -{ - return 0; -} - -size_t IconDatabase::iconRecordCount() -{ - return 0; -} - -size_t IconDatabase::iconRecordCountWithData() -{ - return 0; -} - -void IconDatabase::setClient(IconDatabaseClient*) -{ -} - -// ************************ -// *** Sync Thread Only *** -// ************************ - -void IconDatabase::importIconURLForPageURL(const String&, const String&) -{ -} - -void IconDatabase::importIconDataForIconURL(PassRefPtr<SharedBuffer>, const String&) -{ -} - -bool IconDatabase::shouldStopThreadActivity() const -{ - return true; -} - -} // namespace WebCore - -#endif // !ENABLE(ICONDATABASE) diff --git a/WebCore/loader/icon/IconLoader.cpp b/WebCore/loader/icon/IconLoader.cpp deleted file mode 100644 index 24562d0..0000000 --- a/WebCore/loader/icon/IconLoader.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 "IconLoader.h" - -#include "Document.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "IconDatabase.h" -#include "Logging.h" -#include "ResourceHandle.h" -#include "ResourceLoadScheduler.h" -#include "ResourceResponse.h" -#include "ResourceRequest.h" -#include "SharedBuffer.h" -#include "SubresourceLoader.h" -#include <wtf/UnusedParam.h> -#include <wtf/text/CString.h> - -using namespace std; - -namespace WebCore { - -IconLoader::IconLoader(Frame* frame) - : m_frame(frame) - , m_loadIsInProgress(false) -{ -} - -PassOwnPtr<IconLoader> IconLoader::create(Frame* frame) -{ - return adoptPtr(new IconLoader(frame)); -} - -IconLoader::~IconLoader() -{ -} - -void IconLoader::startLoading() -{ - if (m_resourceLoader) - return; - - // Set flag so we can detect the case where the load completes before - // SubresourceLoader::create returns. - m_loadIsInProgress = true; - - RefPtr<SubresourceLoader> loader = resourceLoadScheduler()->scheduleSubresourceLoad(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->firstRequest().url() : KURL(), 0); - } -} - -void IconLoader::didReceiveData(SubresourceLoader* unusedLoader, const char*, int unusedSize) -{ -#if LOG_DISABLED - UNUSED_PARAM(unusedLoader); - UNUSED_PARAM(unusedSize); -#endif - LOG(IconDatabase, "IconLoader::didReceiveData() - Loader %p, number of bytes %i", unusedLoader, unusedSize); -} - -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->firstRequest().url() : KURL(), 0); - } -} - -void IconLoader::didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&) -{ - // 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->firstRequest().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) { - LOG(IconDatabase, "IconLoader::finishLoading() - Committing iconURL %s to database", iconURL.string().ascii().data()); - m_frame->loader()->commitIconURLToIconDatabase(iconURL); - // Setting the icon data only after committing to the database ensures that the data is - // kept in memory (so it does not have to be read from the database asynchronously), since - // there is a page URL referencing it. - iconDatabase()->setIconDataForIconURL(data, iconURL.string()); - 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 1ebac48..0000000 --- a/WebCore/loader/icon/IconLoader.h +++ /dev/null @@ -1,69 +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 <wtf/Forward.h> -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Frame; -class KURL; -class SharedBuffer; - -class IconLoader : private SubresourceLoaderClient, public Noncopyable { -public: - static PassOwnPtr<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 7e90d8e..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 <wtf/text/CString.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&) -{ - // 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 f1fe12f..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 "PlatformString.h" -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#include <wtf/text/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 f7ccb8f..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 : public 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/icon/wince/IconDatabaseWinCE.cpp b/WebCore/loader/icon/wince/IconDatabaseWinCE.cpp deleted file mode 100644 index 54a36e5..0000000 --- a/WebCore/loader/icon/wince/IconDatabaseWinCE.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2007-2009 Torch Mobile 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. - * - */ - -#include "config.h" -#include "IconDatabase.h" - -#include "AutodrainedPool.h" -#include "DocumentLoader.h" -#include "FileSystem.h" -#include "IconDatabaseClient.h" -#include "IconRecord.h" -#include "Image.h" -#include <wtf/text/CString.h> - -namespace WebCore { - -// Function to obtain the global icon database. -IconDatabase* iconDatabase() { return 0; } - -IconDatabase::IconDatabase() {} -IconDatabase::~IconDatabase() {} - -void IconDatabase::setClient(IconDatabaseClient*) {} - -bool IconDatabase::open(const String& path) { return false; } -void IconDatabase::close() {} - -void IconDatabase::removeAllIcons() {} - -Image* IconDatabase::iconForPageURL(const String&, const IntSize&) { return 0; } -void IconDatabase::readIconForPageURLFromDisk(const String&) {} -String IconDatabase::iconURLForPageURL(const String&) { return String(); } -Image* IconDatabase::defaultIcon(const IntSize&) { return 0;} - -void IconDatabase::retainIconForPageURL(const String&) {} -void IconDatabase::releaseIconForPageURL(const String&) {} - -void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&) {} -void IconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL) {} - -IconLoadDecision IconDatabase::loadDecisionForIconURL(const String&, DocumentLoader*) { return IconLoadNo; } -bool IconDatabase::iconDataKnownForIconURL(const String&) { return false; } - -void IconDatabase::setEnabled(bool enabled) {} -bool IconDatabase::isEnabled() const { return false; } - -void IconDatabase::setPrivateBrowsingEnabled(bool flag) {} -bool IconDatabase::isPrivateBrowsingEnabled() const { return false; } - -void IconDatabase::delayDatabaseCleanup() {} -void IconDatabase::allowDatabaseCleanup() {} -void IconDatabase::checkIntegrityBeforeOpening() {} - -// Support for WebCoreStatistics in WebKit -size_t IconDatabase::pageURLMappingCount() { return 0; } -size_t IconDatabase::retainedPageURLCount() {return 0; } -size_t IconDatabase::iconRecordCount() { return 0; } -size_t IconDatabase::iconRecordCountWithData() { return 0; } - -bool IconDatabase::isOpen() const { return false; } -String IconDatabase::databasePath() const { return String(); } -String IconDatabase::defaultDatabaseFilename() { return String(); } - -} // namespace WebCore diff --git a/WebCore/loader/mac/DocumentLoaderMac.cpp b/WebCore/loader/mac/DocumentLoaderMac.cpp deleted file mode 100644 index 8cc40d2..0000000 --- a/WebCore/loader/mac/DocumentLoaderMac.cpp +++ /dev/null @@ -1,84 +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" -#include <wtf/UnusedParam.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); -#else - UNUSED_PARAM(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); -#else - UNUSED_PARAM(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 25fe7bd..0000000 --- a/WebCore/loader/mac/ResourceLoaderMac.mm +++ /dev/null @@ -1,45 +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*, NSCachedURLResponse* response) -{ - if (!m_sendResourceLoadCallbacks) - return 0; - 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(); -} - -} |