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 /Source/WebCore/loader/archive | |
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 'Source/WebCore/loader/archive')
-rw-r--r-- | Source/WebCore/loader/archive/Archive.h | 62 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveFactory.cpp | 96 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveFactory.h | 50 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveResource.cpp | 62 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveResource.h | 62 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveResourceCollection.cpp | 89 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/ArchiveResourceCollection.h | 59 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp | 591 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/cf/LegacyWebArchive.h | 70 | ||||
-rw-r--r-- | Source/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm | 76 |
10 files changed, 1217 insertions, 0 deletions
diff --git a/Source/WebCore/loader/archive/Archive.h b/Source/WebCore/loader/archive/Archive.h new file mode 100644 index 0000000..af3d8b1 --- /dev/null +++ b/Source/WebCore/loader/archive/Archive.h @@ -0,0 +1,62 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveFactory.cpp b/Source/WebCore/loader/archive/ArchiveFactory.cpp new file mode 100644 index 0000000..5926690 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveFactory.cpp @@ -0,0 +1,96 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveFactory.h b/Source/WebCore/loader/archive/ArchiveFactory.h new file mode 100644 index 0000000..c3b9464 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveFactory.h @@ -0,0 +1,50 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveResource.cpp b/Source/WebCore/loader/archive/ArchiveResource.cpp new file mode 100644 index 0000000..7dedc93 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveResource.cpp @@ -0,0 +1,62 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveResource.h b/Source/WebCore/loader/archive/ArchiveResource.h new file mode 100644 index 0000000..97d6e32 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveResource.h @@ -0,0 +1,62 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveResourceCollection.cpp b/Source/WebCore/loader/archive/ArchiveResourceCollection.cpp new file mode 100644 index 0000000..6eb1237 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveResourceCollection.cpp @@ -0,0 +1,89 @@ +/* + * 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/Source/WebCore/loader/archive/ArchiveResourceCollection.h b/Source/WebCore/loader/archive/ArchiveResourceCollection.h new file mode 100644 index 0000000..9d630d1 --- /dev/null +++ b/Source/WebCore/loader/archive/ArchiveResourceCollection.h @@ -0,0 +1,59 @@ +/* + * 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/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp b/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp new file mode 100644 index 0000000..ddd564e --- /dev/null +++ b/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp @@ -0,0 +1,591 @@ +/* + * 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/Source/WebCore/loader/archive/cf/LegacyWebArchive.h b/Source/WebCore/loader/archive/cf/LegacyWebArchive.h new file mode 100644 index 0000000..8c8f2e4 --- /dev/null +++ b/Source/WebCore/loader/archive/cf/LegacyWebArchive.h @@ -0,0 +1,70 @@ +/* + * 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/Source/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm b/Source/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm new file mode 100644 index 0000000..6a35753 --- /dev/null +++ b/Source/WebCore/loader/archive/cf/LegacyWebArchiveMac.mm @@ -0,0 +1,76 @@ +/* + * 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); +} + +} |