WebCore:
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Mar 2008 17:11:16 +0000 (17:11 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Mar 2008 17:11:16 +0000 (17:11 +0000)
2008-03-25  Brady Eidson  <beidson@apple.com>

        Reviewed by Darin

        <rdar://problem/4516169> - Support WebArchives on Windows
        And pave the way for many future WebArchive bug fixes and enhancements

        This patch accomplishes two main goals:
        1 - Consolidates much of the spread out WebKitMac archive code into one place in WebCore.  This allows for cleaner refactoring
            in the future as well as adding more archive formats with ease.
        2 - Hooks up WebArchive support on Windows.  Safari-style .webarchive files are nothing more than property lists readable by
            CoreFoundation.  While there are still some outstanding issues, including an NSKeyedArchiver chunk of data for the
            ResourceResponse for each resource, this patch manually parses through the property list on CoreFoundation platforms and
            gets many archives loading on Windows

        My goal for this first cut was zero behavior change.  As such, I went for a direct port of the WebKitMac code.  There will be
        opportunities for redesign and refactoring as followups.

        * WebCore.base.exp:

        * loader/DocumentLoader.cpp:
        (WebCore::DocumentLoader::setupForReplaceByMIMEType): Ported from WebKitMac, WebDataSource
        (WebCore::DocumentLoader::addAllArchiveResources):
        (WebCore::DocumentLoader::addArchiveResource):
        (WebCore::DocumentLoader::archiveResourceForURL):
        (WebCore::DocumentLoader::popArchiveForSubframe):
        (WebCore::DocumentLoader::clearArchiveResources):
        * loader/DocumentLoader.h:

        * loader/FrameLoader.cpp: Moved WebFrameLoaderClient and WebFrame code down into their more appropriate FrameLoader home
        (WebCore::FrameLoader::FrameLoader):
        (WebCore::FrameLoader::setDefersLoading):
        (WebCore::FrameLoader::deliverArchivedResourcesAfterDelay):
        (WebCore::FrameLoader::archiveResourceDeliveryTimerFired):
        (WebCore::FrameLoader::loadURLIntoChildFrame):
        (WebCore::FrameLoader::loadArchive):
        (WebCore::FrameLoader::scheduleArchiveLoad):
        (WebCore::FrameLoader::stopAllLoaders):
        (WebCore::FrameLoader::cancelPendingArchiveLoad):
        (WebCore::FrameLoader::isArchiveLoadPending):
        (WebCore::FrameLoader::finishedLoadingDocument):
        * loader/FrameLoader.h:

        * loader/ResourceLoader.cpp:
        (WebCore::ResourceLoader::load):

        * loader/archive/Archive.h: Generic "Archive of web resources" class that is only useful when subclassed.
            Contains a MainResource, subresources, and Archives for subframes
        (WebCore::Archive::mainResource):
        (WebCore::Archive::subresources):
        (WebCore::Archive::subframeArchives):
        (WebCore::Archive::setMainResource):
        (WebCore::Archive::addSubresource):
        (WebCore::Archive::addSubframeArchive):

        * loader/archive/ArchiveFactory.cpp: A class that will take raw archive data and the MIMEtype, and create the
            appropriate Archive class for it.  Additionally it handles registering the known MIMEtypes for all known archive formats
        (WebCore::archiveFactoryCreate):
        (WebCore::archiveMIMETypes):
        (WebCore::ArchiveFactory::isArchiveMimeType):
        (WebCore::ArchiveFactory::create):
        (WebCore::ArchiveFactory::registerKnownArchiveMIMETypes):
        * loader/archive/ArchiveFactory.h:

        * loader/archive/ArchiveResource.cpp: Analog to "WebResource" in WebKitMac.  Contains the data and other important
            attributes of an archived resource
        (WebCore::ArchiveResource::create):
        (WebCore::ArchiveResource::ArchiveResource):
        (WebCore::ArchiveResource::response):
        * loader/archive/ArchiveResource.h:
        (WebCore::ArchiveResource::data):
        (WebCore::ArchiveResource::url):
        (WebCore::ArchiveResource::mimeType):
        (WebCore::ArchiveResource::textEncoding):
        (WebCore::ArchiveResource::frameName):
        (WebCore::ArchiveResource::ignoreWhenUnarchiving):
        (WebCore::ArchiveResource::shouldIgnoreWhenUnarchiving):

        * loader/archive/ArchiveResourceCollection.cpp: Analog of "WebUnarchivingState" in WebKitMac.  Contains a hash of
            all the resources for every frame in an archive, and contains the archives for each subframe needed to load a multi-frame archive
        (WebCore::ArchiveResourceCollection::ArchiveResourceCollection):
        (WebCore::ArchiveResourceCollection::addAllResources):
        (WebCore::ArchiveResourceCollection::addResource):
        (WebCore::ArchiveResourceCollection::archiveResourceForURL):
        (WebCore::ArchiveResourceCollection::popSubframeArchive):
        * loader/archive/ArchiveResourceCollection.h:

        * loader/archive/cf/LegacyWebArchive.cpp: Subclass of Archive specifically for Webkit's Objective-C based ".webarchive" format.
            Mostly a collection of static methods involved in parsing and serializing a WebKit-style .webarchive.  Is mostly supported
            for any CF platform.
        (WebCore::createPropertyListRepresentationFromResource):
        (WebCore::createPropertyListRep):
        (WebCore::createResourceResponseFromPropertyListData):
        (WebCore::createResource):
        (WebCore::LegacyWebArchive::create):
        (WebCore::LegacyWebArchive::LegacyWebArchive):
        (WebCore::LegacyWebArchive::init):
        (WebCore::LegacyWebArchive::extract):
        (WebCore::LegacyWebArchive::rawDataRepresentation):
        (WebCore::createResourceResponseFromMacArchivedData):
        (WebCore::propertyListDataFromResourceResponse):
        * loader/archive/cf/LegacyWebArchive.h:
        * loader/archive/cf/LegacyWebArchiveMac.mm:
        (WebCore::createResourceResponseFromMacArchivedData):
        (WebCore::propertyListDataFromResourceResponse):

        * platform/network/mac/ResourceRequest.h:
        * platform/network/mac/ResourceRequestMac.mm:
        (WebCore::ResourceRequest::applyWebArchiveHackForMail): Tweak the resource request for Mac clients when loading WebArchives

WebKit:

2008-03-25  Brady Eidson  <beidson@apple.com>

        Reviewed by Darin

        <rdar://problem/4516169> - Support WebArchives on Windows

        * WebKit.xcodeproj/project.pbxproj:

WebKit/mac:

2008-03-25  Brady Eidson  <beidson@apple.com>

        Reviewed by Darin

        <rdar://problem/4516169> - Support WebArchives on Windows
        And paves the way for many future WebArchive bug fixes and enhancements

        This change moves most of the real workhorse code about WebArchives into WebCore.  It maintains
        1-to-1 relationships between a few objects in WebCore and WebKit.  Such as:
         * WebArchive <-> LegacyWebArchive
         * WebResource <-> ArchiveResource
         * WebUnarchivingState <-> ArchiveResourceCollection

        The other biggest changes involve many FrameLoaderClient methods that existed soley for WebArchives
        and now exist in WebCore

        * WebCoreSupport/WebFrameLoaderClient.mm:
        (WebFrameLoaderClient::clearUnarchivingState): Emptied - to be removed in a followup patch
        (WebFrameLoaderClient::finalSetupForReplace):
        (WebFrameLoaderClient::setDefersLoading):
        (WebFrameLoaderClient::willUseArchive):
        (WebFrameLoaderClient::isArchiveLoadPending):
        (WebFrameLoaderClient::cancelPendingArchiveLoad):
        (WebFrameLoaderClient::clearArchivedResources):
        (WebFrameLoaderClient::createFrame):

        * WebView/WebArchive.mm:
        (+[WebArchivePrivate initialize]):
        (-[WebArchivePrivate init]):
        (-[WebArchivePrivate initWithCoreArchive:]):
        (-[WebArchivePrivate coreArchive]):
        (-[WebArchivePrivate setCoreArchive:]):
        (-[WebArchivePrivate dealloc]):
        (-[WebArchivePrivate finalize]):
        (-[WebArchive init]):
        (-[WebArchive initWithMainResource:subresources:subframeArchives:]):
        (-[WebArchive initWithData:]):
        (-[WebArchive initWithCoder:]):
        (-[WebArchive encodeWithCoder:]):
        (-[WebArchive mainResource]):
        (-[WebArchive subresources]):
        (-[WebArchive subframeArchives]):
        (-[WebArchive data]):
        (-[WebArchive _initWithCoreLegacyWebArchive:WebCore::]):
        (-[WebArchive WebCore::]):
        * WebView/WebArchiveInternal.h: Added.

        * WebView/WebDataSource.mm:
        (-[WebDataSourcePrivate dealloc]):
        (-[WebDataSource _addSubframeArchives:]):
        (-[WebDataSource _documentFragmentWithArchive:]):
        (-[WebDataSource subresourceForURL:]):
        (-[WebDataSource addSubresource:]):
        * WebView/WebDataSourceInternal.h:

        * WebView/WebFrame.mm:
        (-[WebFrame loadArchive:]):
        * WebView/WebFrameInternal.h:

        * WebView/WebHTMLRepresentation.mm:
        (-[WebHTMLRepresentation finishedLoadingWithDataSource:]):

        * WebView/WebResource.mm:
        (+[WebResourcePrivate initialize]):
        (-[WebResourcePrivate init]):
        (-[WebResourcePrivate initWithCoreResource:]):
        (-[WebResourcePrivate dealloc]):
        (-[WebResourcePrivate finalize]):
        (-[WebResource initWithCoder:]):
        (-[WebResource encodeWithCoder:]):
        (-[WebResource data]):
        (-[WebResource URL]):
        (-[WebResource MIMEType]):
        (-[WebResource textEncodingName]):
        (-[WebResource frameName]):
        (-[WebResource _initWithCoreResource:WebCore::]):
        (-[WebResource WebCore::]):
        (-[WebResource _ignoreWhenUnarchiving]):
        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
        (-[WebResource _fileWrapperRepresentation]):
        (-[WebResource _response]):
        (-[WebResource _stringValue]):
        * WebView/WebResourceInternal.h: Added.
        * WebView/WebResourcePrivate.h:

        * WebView/WebUnarchivingState.h: Removed.
        * WebView/WebUnarchivingState.m: Removed.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@31281 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/loader/DocumentLoader.cpp
WebCore/loader/DocumentLoader.h
WebCore/loader/FrameLoader.cpp
WebCore/loader/FrameLoader.h
WebCore/loader/ResourceLoader.cpp
WebCore/loader/archive/Archive.h
WebCore/loader/archive/ArchiveFactory.cpp
WebCore/loader/archive/ArchiveFactory.h
WebCore/loader/archive/ArchiveResource.cpp
WebCore/loader/archive/ArchiveResource.h
WebCore/loader/archive/ArchiveResourceCollection.cpp
WebCore/loader/archive/ArchiveResourceCollection.h
WebCore/loader/archive/cf/LegacyWebArchive.cpp
WebCore/loader/archive/cf/LegacyWebArchive.h
WebCore/loader/archive/cf/LegacyWebArchiveMac.mm
WebCore/platform/network/mac/ResourceRequest.h
WebCore/platform/network/mac/ResourceRequestMac.mm
WebKit/ChangeLog
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/mac/ChangeLog
WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm
WebKit/mac/WebView/WebArchive.mm
WebKit/mac/WebView/WebArchiveInternal.h [moved from WebKit/mac/WebView/WebUnarchivingState.h with 74% similarity]
WebKit/mac/WebView/WebDataSource.mm
WebKit/mac/WebView/WebDataSourceInternal.h
WebKit/mac/WebView/WebFrame.mm
WebKit/mac/WebView/WebFrameInternal.h
WebKit/mac/WebView/WebHTMLRepresentation.mm
WebKit/mac/WebView/WebResource.mm
WebKit/mac/WebView/WebResourceInternal.h [new file with mode: 0644]
WebKit/mac/WebView/WebResourcePrivate.h
WebKit/mac/WebView/WebUnarchivingState.m [deleted file]

index d98c86a..16fc5b8 100644 (file)
@@ -1,3 +1,113 @@
+2008-03-25  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Darin
+
+        <rdar://problem/4516169> - Support WebArchives on Windows
+        And pave the way for many future WebArchive bug fixes and enhancements
+
+        This patch accomplishes two main goals:
+        1 - Consolidates much of the spread out WebKitMac archive code into one place in WebCore.  This allows for cleaner refactoring 
+            in the future as well as adding more archive formats with ease.
+        2 - Hooks up WebArchive support on Windows.  Safari-style .webarchive files are nothing more than property lists readable by
+            CoreFoundation.  While there are still some outstanding issues, including an NSKeyedArchiver chunk of data for the 
+            ResourceResponse for each resource, this patch manually parses through the property list on CoreFoundation platforms and
+            gets many archives loading on Windows
+
+        My goal for this first cut was zero behavior change.  As such, I went for a direct port of the WebKitMac code.  There will be
+        opportunities for redesign and refactoring as followups.
+
+        * WebCore.base.exp:
+
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::setupForReplaceByMIMEType): Ported from WebKitMac, WebDataSource
+        (WebCore::DocumentLoader::addAllArchiveResources):
+        (WebCore::DocumentLoader::addArchiveResource):
+        (WebCore::DocumentLoader::archiveResourceForURL):
+        (WebCore::DocumentLoader::popArchiveForSubframe):
+        (WebCore::DocumentLoader::clearArchiveResources):
+        * loader/DocumentLoader.h:
+
+        * loader/FrameLoader.cpp: Moved WebFrameLoaderClient and WebFrame code down into their more appropriate FrameLoader home
+        (WebCore::FrameLoader::FrameLoader):
+        (WebCore::FrameLoader::setDefersLoading):
+        (WebCore::FrameLoader::deliverArchivedResourcesAfterDelay):
+        (WebCore::FrameLoader::archiveResourceDeliveryTimerFired):
+        (WebCore::FrameLoader::loadURLIntoChildFrame):
+        (WebCore::FrameLoader::loadArchive):
+        (WebCore::FrameLoader::scheduleArchiveLoad):
+        (WebCore::FrameLoader::stopAllLoaders):
+        (WebCore::FrameLoader::cancelPendingArchiveLoad):
+        (WebCore::FrameLoader::isArchiveLoadPending):
+        (WebCore::FrameLoader::finishedLoadingDocument):
+        * loader/FrameLoader.h:
+
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::load):
+
+        * loader/archive/Archive.h: Generic "Archive of web resources" class that is only useful when subclassed.  
+            Contains a MainResource, subresources, and Archives for subframes
+        (WebCore::Archive::mainResource):
+        (WebCore::Archive::subresources):
+        (WebCore::Archive::subframeArchives):
+        (WebCore::Archive::setMainResource):
+        (WebCore::Archive::addSubresource):
+        (WebCore::Archive::addSubframeArchive):
+
+        * loader/archive/ArchiveFactory.cpp: A class that will take raw archive data and the MIMEtype, and create the
+            appropriate Archive class for it.  Additionally it handles registering the known MIMEtypes for all known archive formats
+        (WebCore::archiveFactoryCreate):
+        (WebCore::archiveMIMETypes):
+        (WebCore::ArchiveFactory::isArchiveMimeType):
+        (WebCore::ArchiveFactory::create):
+        (WebCore::ArchiveFactory::registerKnownArchiveMIMETypes):
+        * loader/archive/ArchiveFactory.h:
+
+        * loader/archive/ArchiveResource.cpp: Analog to "WebResource" in WebKitMac.  Contains the data and other important
+            attributes of an archived resource
+        (WebCore::ArchiveResource::create):
+        (WebCore::ArchiveResource::ArchiveResource):
+        (WebCore::ArchiveResource::response):
+        * loader/archive/ArchiveResource.h:
+        (WebCore::ArchiveResource::data):
+        (WebCore::ArchiveResource::url):
+        (WebCore::ArchiveResource::mimeType):
+        (WebCore::ArchiveResource::textEncoding):
+        (WebCore::ArchiveResource::frameName):
+        (WebCore::ArchiveResource::ignoreWhenUnarchiving):
+        (WebCore::ArchiveResource::shouldIgnoreWhenUnarchiving):
+
+        * loader/archive/ArchiveResourceCollection.cpp: Analog of "WebUnarchivingState" in WebKitMac.  Contains a hash of
+            all the resources for every frame in an archive, and contains the archives for each subframe needed to load a multi-frame archive
+        (WebCore::ArchiveResourceCollection::ArchiveResourceCollection):
+        (WebCore::ArchiveResourceCollection::addAllResources):
+        (WebCore::ArchiveResourceCollection::addResource):
+        (WebCore::ArchiveResourceCollection::archiveResourceForURL):
+        (WebCore::ArchiveResourceCollection::popSubframeArchive):
+        * loader/archive/ArchiveResourceCollection.h:
+
+        * loader/archive/cf/LegacyWebArchive.cpp: Subclass of Archive specifically for Webkit's Objective-C based ".webarchive" format.
+            Mostly a collection of static methods involved in parsing and serializing a WebKit-style .webarchive.  Is mostly supported
+            for any CF platform.
+        (WebCore::createPropertyListRepresentationFromResource):
+        (WebCore::createPropertyListRep):
+        (WebCore::createResourceResponseFromPropertyListData):
+        (WebCore::createResource):
+        (WebCore::LegacyWebArchive::create):
+        (WebCore::LegacyWebArchive::LegacyWebArchive):
+        (WebCore::LegacyWebArchive::init):
+        (WebCore::LegacyWebArchive::extract):
+        (WebCore::LegacyWebArchive::rawDataRepresentation):
+        (WebCore::createResourceResponseFromMacArchivedData):
+        (WebCore::propertyListDataFromResourceResponse):
+        * loader/archive/cf/LegacyWebArchive.h:
+        * loader/archive/cf/LegacyWebArchiveMac.mm:
+        (WebCore::createResourceResponseFromMacArchivedData):
+        (WebCore::propertyListDataFromResourceResponse):
+
+        * platform/network/mac/ResourceRequest.h:
+        * platform/network/mac/ResourceRequestMac.mm:
+        (WebCore::ResourceRequest::applyWebArchiveHackForMail): Tweak the resource request for Mac clients when loading WebArchives
+
 2008-03-25  David Hyatt  <hyatt@apple.com>
 
         Cut and paste error in the zoom code.  A width() should have been a height().  Regression tests caught this.
index 320006d..b980e86 100644 (file)
@@ -138,6 +138,7 @@ __ZN7WebCore11EditCommand7unapplyEv
 __ZN7WebCore11FileChooser10chooseFileERKNS_6StringE
 __ZN7WebCore11FileChooserD1Ev
 __ZN7WebCore11FrameLoader11completeURLERKNS_6StringE
+__ZN7WebCore11FrameLoader11loadArchiveEN3WTF10PassRefPtrINS_7ArchiveEEE
 __ZN7WebCore11FrameLoader11setEncodingERKNS_6StringEb
 __ZN7WebCore11FrameLoader12canCachePageEv
 __ZN7WebCore11FrameLoader12shouldReloadERKNS_4KURLES3_
@@ -150,6 +151,7 @@ __ZN7WebCore11FrameLoader17stopForUserCancelEb
 __ZN7WebCore11FrameLoader18currentHistoryItemEv
 __ZN7WebCore11FrameLoader18shouldHideReferrerERKNS_4KURLERKNS_6StringE
 __ZN7WebCore11FrameLoader20continueLoadWithDataEPNS_12SharedBufferERKNS_6StringES5_RKNS_4KURLE
+__ZN7WebCore11FrameLoader21loadURLIntoChildFrameERKNS_4KURLERKNS_6StringEPNS_5FrameE
 __ZN7WebCore11FrameLoader21setCurrentHistoryItemEN3WTF10PassRefPtrINS_11HistoryItemEEE
 __ZN7WebCore11FrameLoader22findFrameForNavigationERKNS_12AtomicStringE
 __ZN7WebCore11FrameLoader22setPreviousHistoryItemEN3WTF10PassRefPtrINS_11HistoryItemEEE
@@ -265,8 +267,11 @@ __ZN7WebCore13toDeviceSpaceERKNS_9FloatRectEP8NSWindow
 __ZN7WebCore14CachedResource5derefEPNS_20CachedResourceClientE
 __ZN7WebCore14DocumentLoader13attachToFrameEv
 __ZN7WebCore14DocumentLoader15detachFromFrameEv
+__ZN7WebCore14DocumentLoader18addArchiveResourceEN3WTF10PassRefPtrINS_15ArchiveResourceEEE
 __ZN7WebCore14DocumentLoader19prepareForLoadStartEv
 __ZN7WebCore14DocumentLoader21addPlugInStreamLoaderEPNS_14ResourceLoaderE
+__ZN7WebCore14DocumentLoader21archiveResourceForURLERKNS_4KURLE
+__ZN7WebCore14DocumentLoader22addAllArchiveResourcesEPNS_7ArchiveE
 __ZN7WebCore14DocumentLoader22cancelMainResourceLoadERKNS_13ResourceErrorE
 __ZN7WebCore14DocumentLoader24removePlugInStreamLoaderEPNS_14ResourceLoaderE
 __ZN7WebCore14DocumentLoader32replaceRequestURLForAnchorScrollERKNS_4KURLE
@@ -284,6 +289,8 @@ __ZN7WebCore14ResourceHandle12releaseProxyEv
 __ZN7WebCore14ResourceLoader14cancelledErrorEv
 __ZN7WebCore14ResourceLoader19setShouldBufferDataEb
 __ZN7WebCore14SecurityOrigin6createERKNS_6StringES3_tPS0_
+__ZN7WebCore15ArchiveResource6createEN3WTF10PassRefPtrINS_12SharedBufferEEERKNS_4KURLERKNS_6StringESA_SA_RKNS_16ResourceResponseE
+__ZN7WebCore15ArchiveResource8responseEv
 __ZN7WebCore15BackForwardList10removeItemEPNS_11HistoryItemE
 __ZN7WebCore15BackForwardList10setEnabledEb
 __ZN7WebCore15BackForwardList11currentItemEv
@@ -332,6 +339,10 @@ __ZN7WebCore15StringTruncator5widthERKNS_6StringERKNS_4FontEb
 __ZN7WebCore15VisiblePositionC1ERKNS_8PositionENS_9EAffinityE
 __ZN7WebCore16FontPlatformDataC1EP6NSFontbb
 __ZN7WebCore16FontPlatformDataD1Ev
+__ZN7WebCore16LegacyWebArchive21rawDataRepresentationEv
+__ZN7WebCore16LegacyWebArchive6createEN3WTF10PassRefPtrINS_15ArchiveResourceEEERNS1_6VectorIS4_Lm0EEERNS5_INS2_IS0_EELm0EEE
+__ZN7WebCore16LegacyWebArchive6createEPNS_12SharedBufferE
+__ZN7WebCore16LegacyWebArchive6createEv
 __ZN7WebCore16MIMETypeRegistry24isSupportedImageMIMETypeERKNS_6StringE
 __ZN7WebCore16MIMETypeRegistry26getSupportedImageMIMETypesEv
 __ZN7WebCore16MIMETypeRegistry29getSupportedNonImageMIMETypesEv
index 1aedaa9..79506d1 100644 (file)
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "DocumentLoader.h"
 
+#include "ArchiveResourceCollection.h"
 #include "CachedPage.h"
 #include "DocLoader.h"
 #include "Document.h"
@@ -42,6 +43,7 @@
 #include "SharedBuffer.h"
 #include "StringBuffer.h"
 #include "XMLTokenizer.h"
+
 #include <wtf/Assertions.h>
 #include <wtf/unicode/Unicode.h>
 
@@ -364,8 +366,7 @@ void DocumentLoader::setupForReplaceByMIMEType(const String& newMIMEType)
     
     stopLoadingSubresources();
     stopLoadingPlugIns();
-
-    frameLoader()->finalSetupForReplace(this);
+    clearArchiveResources();
 }
 
 void DocumentLoader::updateLoading()
@@ -438,6 +439,52 @@ bool DocumentLoader::isLoadingInAPISense() const
     return frameLoader()->subframeIsLoading();
 }
 
+void DocumentLoader::addAllArchiveResources(Archive* archive)
+{
+    if (!m_archiveResourceCollection)
+        m_archiveResourceCollection.set(new ArchiveResourceCollection);
+        
+    ASSERT(archive);
+    if (!archive)
+        return;
+        
+    m_archiveResourceCollection->addAllResources(archive);
+}
+
+// FIXME: Adding a resource directly to a DocumentLoader/ArchiveResourceCollection seems like bad design, but is API some apps rely on.
+// Can we change the design in a manner that will let us deprecate that API without reducing functionality of those apps?
+void DocumentLoader::addArchiveResource(PassRefPtr<ArchiveResource> resource)
+{
+    if (!m_archiveResourceCollection)
+        m_archiveResourceCollection.set(new ArchiveResourceCollection);
+        
+    ASSERT(resource);
+    if (!resource)
+        return;
+        
+    m_archiveResourceCollection->addResource(resource);
+}
+
+ArchiveResource* DocumentLoader::archiveResourceForURL(const KURL& url)
+{
+    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();
+}
+
 void DocumentLoader::addResponse(const ResourceResponse& r)
 {
     if (!m_stopRecordingResponses)
index 4b77dcc..1ab1d8a 100644 (file)
@@ -43,6 +43,9 @@
 
 namespace WebCore {
 
+    class Archive;
+    class ArchiveResource;
+    class ArchiveResourceCollection;
     class CachedPage;
     class Frame;
     class FrameLoader;
@@ -117,6 +120,12 @@ namespace WebCore {
         void unschedule(SchedulePair*);
 #endif
 
+        void addAllArchiveResources(Archive*);
+        void addArchiveResource(PassRefPtr<ArchiveResource>);
+        ArchiveResource* archiveResourceForURL(const KURL&);
+        PassRefPtr<Archive> popArchiveForSubframe(const String& frameName);
+        void clearArchiveResources();
+        
         void addResponse(const ResourceResponse&);
         const ResponseVector& responses() const { return m_responses; }
 
@@ -225,6 +234,8 @@ namespace WebCore {
         // page cache.
         ResponseVector m_responses;
         bool m_stopRecordingResponses;
+        
+        OwnPtr<ArchiveResourceCollection> m_archiveResourceCollection;
     };
 
 }
index fb8a005..1ebdc55 100644 (file)
@@ -30,6 +30,8 @@
 #include "config.h"
 #include "FrameLoader.h"
 
+#include "Archive.h"
+#include "ArchiveFactory.h"
 #include "CString.h"
 #include "Cache.h"
 #include "CachedPage.h"
@@ -254,6 +256,7 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
     , m_isDisplayingInitialEmptyDocument(false)
     , m_committedFirstRealDocumentLoad(false)
     , m_didPerformFirstNavigation(false)
+    , m_archiveResourceDeliveryTimer(this, &FrameLoader::archiveResourceDeliveryTimerFired)
 #ifndef NDEBUG
     , m_didDispatchDidCommitLoad(false)
 #endif
@@ -301,7 +304,8 @@ void FrameLoader::setDefersLoading(bool defers)
         m_provisionalDocumentLoader->setDefersLoading(defers);
     if (m_policyDocumentLoader)
         m_policyDocumentLoader->setDefersLoading(defers);
-    m_client->setDefersLoading(defers);
+    if (!defers)
+        deliverArchivedResourcesAfterDelay();
 }
 
 Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
@@ -1488,6 +1492,108 @@ void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
     ASSERT_NOT_REACHED();
 }
 
+void FrameLoader::deliverArchivedResourcesAfterDelay()
+{
+    if (m_pendingArchiveResources.isEmpty())
+        return;
+    if (m_frame->page()->defersLoading())
+        return;
+    if (!m_archiveResourceDeliveryTimer.isActive())
+        m_archiveResourceDeliveryTimer.startOneShot(0);
+}
+
+void FrameLoader::archiveResourceDeliveryTimerFired(Timer<FrameLoader>*)
+{
+    if (m_pendingArchiveResources.isEmpty())
+        return;
+    if (m_frame->page()->defersLoading())
+        return;
+
+    ArchiveResourceMap copy;
+    copy.swap(m_pendingArchiveResources);
+
+    ArchiveResourceMap::const_iterator end = copy.end();
+    for (ArchiveResourceMap::const_iterator it = copy.begin(); it != end; ++it) {
+        RefPtr<ResourceLoader> loader = it->first;
+        ArchiveResource* resource = it->second.get();
+        
+        SharedBuffer* data = resource->data();
+        
+        loader->didReceiveResponse(resource->response());
+        loader->didReceiveData(data->data(), data->size(), data->size(), true);
+        loader->didFinishLoading();
+    }
+}
+
+/*
+    In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
+    The item that was the target of the user's navigation is designated as the "targetItem".  
+    When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
+    which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
+*/
+void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
+{
+    ASSERT(childFrame);
+    HistoryItem* parentItem = currentHistoryItem();
+    FrameLoadType loadType = this->loadType();
+    FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
+
+    KURL workingURL = url;
+    
+    // If we're moving in the backforward list, we might want to replace the content
+    // of this child frame with whatever was there at that point.
+    // Reload will maintain the frame contents, LoadSame will not.
+    if (parentItem && parentItem->children().size() &&
+        (isBackForwardLoadType(loadType) || loadType == FrameLoadTypeReloadAllowingStaleData))
+    {
+        HistoryItem* childItem = parentItem->childItemWithName(childFrame->tree()->name());
+        if (childItem) {
+            // Use the original URL to ensure we get all the side-effects, such as
+            // onLoad handlers, of any redirects that happened. An example of where
+            // this is needed is Radar 3213556.
+            workingURL = KURL(childItem->originalURLString());
+            // These behaviors implied by these loadTypes should apply to the child frames
+            childLoadType = loadType;
+
+            if (isBackForwardLoadType(loadType)) {
+                // For back/forward, remember this item so we can traverse any child items as child frames load
+                childFrame->loader()->setProvisionalHistoryItem(childItem);
+            } else {
+                // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
+                childFrame->loader()->setCurrentHistoryItem(childItem);
+            }
+        }
+    }
+
+    RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name());
+    
+    if (subframeArchive)
+        childFrame->loader()->loadArchive(subframeArchive.release());
+    else
+        childFrame->loader()->load(workingURL, referer, childLoadType, String(), 0, 0);
+}
+
+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());
+}
+
 String FrameLoader::encoding() const
 {
     if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
@@ -1933,11 +2039,6 @@ void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
 }
 
-void FrameLoader::finalSetupForReplace(DocumentLoader* loader)
-{
-    m_client->clearUnarchivingState(loader);
-}
-
 void FrameLoader::load(const KURL& url, Event* event)
 {
     load(ResourceRequest(url), false, true, event, 0, HashMap<String, String>());
@@ -2206,9 +2307,24 @@ void FrameLoader::receivedData(const char* data, int length)
     activeDocumentLoader()->receivedData(data, length);
 }
 
-bool FrameLoader::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
+bool FrameLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL)
 {
-    return m_client->willUseArchive(loader, request, originalURL);
+    if (request.url() != originalURL)
+        return false;
+        
+    DocumentLoader* activeLoader = activeDocumentLoader();
+    ASSERT(activeLoader);
+    if (!activeLoader)
+        return false;
+        
+    ArchiveResource* resource = activeLoader->archiveResourceForURL(originalURL);
+    if (!resource)
+        return false;
+
+    m_pendingArchiveResources.set(loader, resource);
+    deliverArchivedResourcesAfterDelay();
+    
+    return true;
 }
 
 void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
@@ -2401,10 +2517,12 @@ void FrameLoader::stopAllLoaders()
     stopLoadingSubframes();
     if (m_provisionalDocumentLoader)
         m_provisionalDocumentLoader->stopLoading();
-    if (m_documentLoader)
+    if (m_documentLoader) {
         m_documentLoader->stopLoading();
+        m_documentLoader->clearArchiveResources();
+        m_archiveResourceDeliveryTimer.stop();
+    }
     setProvisionalDocumentLoader(0);
-    m_client->clearArchivedResources();
 
     m_inStopAllLoaders = false;    
 }
@@ -2421,7 +2539,11 @@ void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
 
 void FrameLoader::cancelPendingArchiveLoad(ResourceLoader* loader)
 {
-    m_client->cancelPendingArchiveLoad(loader);
+    if (m_pendingArchiveResources.isEmpty())
+        return;
+    m_pendingArchiveResources.remove(loader);
+    if (m_pendingArchiveResources.isEmpty())
+        m_archiveResourceDeliveryTimer.stop();
 }
 
 DocumentLoader* FrameLoader::activeDocumentLoader() const
@@ -2811,10 +2933,12 @@ void FrameLoader::finishedLoading()
     checkLoadComplete();
 }
 
+#ifndef NDEBUG
 bool FrameLoader::isArchiveLoadPending(ResourceLoader* loader) const
 {
-    return m_client->isArchiveLoadPending(loader);
+    return m_pendingArchiveResources.contains(loader);
 }
+#endif
 
 bool FrameLoader::isHostedByObjectElement() const
 {
@@ -2857,9 +2981,24 @@ void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
 {
 #if PLATFORM(WIN)
-    if (!m_creatingInitialEmptyDocument)
+    if (m_creatingInitialEmptyDocument)
+        return;
 #endif
-        m_client->finishedLoading(loader);
+    m_client->finishedLoading(loader);
+    
+    // If loading a webarchive, run through webarchive machinery
+    const String& responseMIMEType = loader->responseMIMEType();
+    if (!ArchiveFactory::isArchiveMimeType(responseMIMEType))
+        return;
+        
+    RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType));
+    if (!archive)
+        return;
+
+    loader->addAllArchiveResources(archive.get());
+    
+    ArchiveResource* mainResource = archive->mainResource();
+    continueLoadWithData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), mainResource->url());
 }
 
 bool FrameLoader::isReplacing() const
index dae0985..8e7d55d 100644 (file)
@@ -53,6 +53,8 @@ namespace KJS {
 
 namespace WebCore {
 
+    class Archive;
+    class ArchiveResource;
     class AuthenticationChallenge;
     class CachedPage;
     class Document;
@@ -140,7 +142,6 @@ namespace WebCore {
         void prepareForLoadStart();
         void setupForReplace();
         void setupForReplaceByMIMEType(const String& newMIMEType);
-        void finalSetupForReplace(DocumentLoader*);
         void load(const KURL&, Event*);
         void load(const FrameLoadRequest&, bool lockHistory, bool userGesture,
             Event*, HTMLFormElement*, const HashMap<String, String>& formValues);
@@ -157,6 +158,9 @@ namespace WebCore {
         
         void load(DocumentLoader*);
         void load(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>);
+        
+        void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*);
+        void loadArchive(PassRefPtr<Archive> archive);
 
         static bool canLoad(const KURL&, const String& referrer);
         static bool canLoad(const KURL&, const Document*);
@@ -214,8 +218,10 @@ namespace WebCore {
         ResourceError cancelledError(const ResourceRequest&) const;
         ResourceError fileDoesNotExistError(const ResourceResponse&) const;
         ResourceError blockedError(const ResourceRequest&) const;
-        bool willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL&) const;
+        bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&, const KURL&);
+#ifndef NDEBUG
         bool isArchiveLoadPending(ResourceLoader*) const;
+#endif
         void cannotShowMIMEType(const ResourceResponse&);
         ResourceError interruptionForPolicyChangeError(const ResourceRequest&);
 
@@ -460,6 +466,9 @@ namespace WebCore {
         void redirectionTimerFired(Timer<FrameLoader>*);
         void checkCompletedTimerFired(Timer<FrameLoader>*);
         void checkLoadCompleteTimerFired(Timer<FrameLoader>*);
+        
+        void deliverArchivedResourcesAfterDelay();
+        void archiveResourceDeliveryTimerFired(Timer<FrameLoader>*);
 
         void cancelRedirection(bool newLoadInProgress = false);
 
@@ -639,6 +648,10 @@ namespace WebCore {
         RefPtr<HistoryItem> m_provisionalHistoryItem;
         
         bool m_didPerformFirstNavigation;
+        
+        typedef HashMap<RefPtr<ResourceLoader>, RefPtr<ArchiveResource> > ArchiveResourceMap;
+        ArchiveResourceMap m_pendingArchiveResources;
+        Timer<FrameLoader> m_archiveResourceDeliveryTimer;
 
 #ifndef NDEBUG
         bool m_didDispatchDidCommitLoad;
index dce95b6..57a6bcb 100644 (file)
@@ -115,7 +115,7 @@ bool ResourceLoader::load(const ResourceRequest& r)
         return false;
     }
     
-    if (frameLoader()->willUseArchive(this, clientRequest, r.url()))
+    if (frameLoader()->scheduleArchiveLoad(this, clientRequest, r.url()))
         return true;
     
     if (m_defersLoading) {
index 25aaea3..af3d8b1 100644 (file)
 #ifndef Archive_h
 #define Archive_h
 
-// FIXME:  Code will go here!
+#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
index 3126c63..85fa137 100644 (file)
 #include "config.h"
 #include "ArchiveFactory.h"
 
-// FIXME:  Code will go here!
+#include "LegacyWebArchive.h"
+#include "MIMETypeRegistry.h"
+#include "PlatformString.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+typedef PassRefPtr<Archive> RawDataCreationFunction(SharedBuffer*);
+
+// The create functions in the archive classes return PassRefPtr to concrete subclasses
+// of Archive. This adaptor makes the functions have a uniform return type.
+template <typename ArchiveClass> static PassRefPtr<Archive> archiveFactoryCreate(SharedBuffer* buffer)
+{
+    return ArchiveClass::create(buffer);
+}
+
+static HashMap<String, RawDataCreationFunction*, CaseFoldingHash>& archiveMIMETypes()
+{
+    static HashMap<String, RawDataCreationFunction*, CaseFoldingHash> mimeTypes;
+    static bool initialized = false;
+    
+    if (initialized)
+        return mimeTypes;
+    
+#if PLATFORM(CF)
+    mimeTypes.set("application/x-webarchive", archiveFactoryCreate<LegacyWebArchive>);
+#endif
+        
+    initialized = true;
+    return mimeTypes;
+}
+
+bool ArchiveFactory::isArchiveMimeType(const String& mimeType)
+{
+    return archiveMIMETypes().contains(mimeType);
+}
+
+PassRefPtr<Archive> ArchiveFactory::create(SharedBuffer* data, const String& mimeType)
+{
+    RawDataCreationFunction* function = archiveMIMETypes().get(mimeType);
+    return function ? function(data) : 0;
+}
+
+void ArchiveFactory::registerKnownArchiveMIMETypes()
+{
+    HashSet<String>& mimeTypes = MIMETypeRegistry::getSupportedNonImageMIMETypes();
+    HashMap<String, RawDataCreationFunction*, CaseFoldingHash>::iterator i = archiveMIMETypes().begin();
+    HashMap<String, RawDataCreationFunction*, CaseFoldingHash>::iterator end = archiveMIMETypes().end();
+    
+    for (; i != end; ++i)
+        mimeTypes.add(i->first);
+}
+
+}
index b2f6b11..bf1d5c6 100644 (file)
 #ifndef ArchiveFactory_h
 #define ArchiveFactory_h
 
-// FIXME:  Code will go here!
+#include "Archive.h"
 
-#endif // ArchiveFactory
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+class String;
+
+class ArchiveFactory {
+public:
+    static bool isArchiveMimeType(const String&);
+    static PassRefPtr<Archive> create(SharedBuffer* data, const String& mimeType);
+    static void registerKnownArchiveMIMETypes();
+};
+
+}
+
+#endif // ArchiveFactory_h
index a25b14f..871ab7c 100644 (file)
 #include "config.h"
 #include "ArchiveResource.h"
 
-// FIXME:  Code will go here!
+#include "SharedBuffer.h"
+
+namespace WebCore {
+
+PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName)
+{
+    return adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName));
+}
+
+PassRefPtr<ArchiveResource> ArchiveResource::create(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& resourceResponse)
+{
+    return adoptRef(new ArchiveResource(data, url, mimeType, textEncoding, frameName, resourceResponse));
+}
+
+ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName)
+    : m_data(data)
+    , m_url(url)
+    , m_mimeType(mimeType)
+    , m_textEncoding(textEncoding)
+    , m_frameName(frameName)
+    , m_shouldIgnoreWhenUnarchiving(false)
+{
+}
+
+ArchiveResource::ArchiveResource(PassRefPtr<SharedBuffer> data, const KURL& url, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse& response)
+    : m_data(data)
+    , m_url(url)
+    , m_mimeType(mimeType)
+    , m_textEncoding(textEncoding)
+    , m_frameName(frameName)
+    , m_response(response)
+    , m_shouldIgnoreWhenUnarchiving(false)
+{
+}
+
+const ResourceResponse& ArchiveResource::response()
+{
+    if (!m_response.isNull())
+        return m_response;
+        
+    m_response = ResourceResponse(m_url, m_mimeType, m_data->size(), m_textEncoding, String());
+    return m_response;
+}
+
+}
index 102d598..408e7db 100644 (file)
 #ifndef ArchiveResource_h
 #define ArchiveResource_h
 
-// FIXME:  Code will go here!
+#include "KURL.h"
+#include "PlatformString.h"
+#include "ResourceResponse.h"
+#include "SharedBuffer.h"
 
-#endif // ArchiveResource
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class ArchiveResource : public RefCounted<ArchiveResource> {
+public:
+    static PassRefPtr<ArchiveResource> create(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName);
+    static PassRefPtr<ArchiveResource> create(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse&);
+    
+    SharedBuffer* data() { return m_data.get(); }
+    
+    const KURL& url() const { return m_url; }
+    const String& mimeType() const { return m_mimeType; }
+    const String& textEncoding() const { return m_textEncoding; }
+    const String& frameName() const { return m_frameName; }
+    const ResourceResponse& response();
+    
+    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);
+    ArchiveResource(PassRefPtr<SharedBuffer>, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse&);
+    
+    RefPtr<SharedBuffer> m_data;
+    KURL m_url;
+    String m_mimeType;
+    String m_textEncoding;
+    String m_frameName;
+    
+    ResourceResponse m_response;
+    
+    bool m_shouldIgnoreWhenUnarchiving;
+};
+
+}
+
+#endif // ArchiveResource_h
index 5de3e49..6eb1237 100644 (file)
 #include "config.h"
 #include "ArchiveResourceCollection.h"
 
-// FIXME:  Code will go here!
+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);
+}
+
+}
index 35fbb59..f898a8d 100644 (file)
 #ifndef ArchiveResourceCollection_h
 #define ArchiveResourceCollection_h
 
-// FIXME:  Code will go here!
+#include "Archive.h"
+#include "ArchiveResource.h"
+#include "KURL.h"
+#include "PlatformString.h"
 
-#endif // ArchiveResourceCollection
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class ArchiveResourceCollection : Noncopyable {
+public:
+    ArchiveResourceCollection();
+
+    void addResource(PassRefPtr<ArchiveResource>);
+    void addAllResources(Archive*);
+    
+    ArchiveResource* archiveResourceForURL(const KURL&);
+    PassRefPtr<Archive> popSubframeArchive(const String& frameName);
+    
+private:    
+    HashMap<String, RefPtr<ArchiveResource> > m_subresources;
+    HashMap<String, RefPtr<Archive> > m_subframes;
+};
+
+}
+
+#endif
index 7aab54f..d73d174 100644 (file)
 #include "config.h"
 #include "LegacyWebArchive.h"
 
-// FIXME:  Code will go here!
+#include "KURL.h"
+#include "Logging.h"
+#include "SharedBuffer.h"
+
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+static const CFStringRef LegacyWebArchiveMainResourceKey = CFSTR("WebMainResource");
+static const CFStringRef LegacyWebArchiveSubresourcesKey = CFSTR("WebSubresources");
+static const CFStringRef LegacyWebArchiveSubframeArchivesKey = CFSTR("WebSubframeArchives");
+static const CFStringRef LegacyWebArchiveResourceDataKey = CFSTR("WebResourceData");
+static const CFStringRef LegacyWebArchiveResourceFrameNameKey = CFSTR("WebResourceFrameName");
+static const CFStringRef LegacyWebArchiveResourceMIMETypeKey = CFSTR("WebResourceMIMEType");
+static const CFStringRef LegacyWebArchiveResourceURLKey = CFSTR("WebResourceURL");
+static const CFStringRef LegacyWebArchiveResourceTextEncodingNameKey = CFSTR("WebResourceTextEncodingName");
+static const CFStringRef LegacyWebArchiveResourceResponseKey = CFSTR("WebResourceResponse");
+static const CFStringRef LegacyWebArchiveResourceResponseVersionKey = CFSTR("WebResourceResponseVersion");
+
+static RetainPtr<CFDictionaryRef> createPropertyListRepresentationFromResource(ArchiveResource* resource, bool mainResource)
+{
+    if (!resource) {
+        // The property list representation of a null/empty WebResource has the following 3 objects stored as nil
+        RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, 0));
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, 0);
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, 0);
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, 0);
+
+        return propertyList;
+    }
+    
+    RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 6, 0, &kCFTypeDictionaryValueCallBacks));
+    
+    // Resource data can be empty, but must be represented by an empty CFDataRef
+    SharedBuffer* data = resource->data();
+    RetainPtr<CFDataRef> cfData;
+    if (data)
+        cfData.adoptCF(data->createCFData());
+    else
+        cfData.adoptCF(CFDataCreate(0, 0, 0));
+    CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, cfData.get());
+    
+    // Resource URL cannot be null
+    RetainPtr<CFStringRef> cfURL(AdoptCF, resource->url().string().createCFString());
+    if (cfURL)
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, cfURL.get());
+    else {
+        LOG(Archives, "LegacyWebArchive - NULL resource URL is invalid - returning null property list");
+        return 0;
+    }
+
+    // FrameName should be left out if empty for subresources, but always included for main resources
+    const String& frameName(resource->frameName());
+    if (!frameName.isEmpty() || mainResource) {
+        RetainPtr<CFStringRef> cfFrameName(AdoptCF, frameName.createCFString());
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceFrameNameKey, cfFrameName.get());
+    }
+    
+    // Set MIMEType, TextEncodingName, and ResourceResponse only if they actually exist
+    const String& mimeType(resource->mimeType());
+    if (!mimeType.isEmpty()) {
+        RetainPtr<CFStringRef> cfMIMEType(AdoptCF, mimeType.createCFString());
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, cfMIMEType.get());
+    }
+    
+    const String& textEncoding(resource->textEncoding());
+    if (!textEncoding.isEmpty()) {
+        RetainPtr<CFStringRef> cfTextEncoding(AdoptCF, textEncoding.createCFString());
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceTextEncodingNameKey, cfTextEncoding.get());
+    }
+
+    // Don't include the resource response for the main resource
+    if (!mainResource) {
+        RetainPtr<CFDataRef> resourceResponseData = propertyListDataFromResourceResponse(resource->response());
+        if (resourceResponseData)
+            CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceResponseKey, resourceResponseData.get());    
+    }
+    
+    return propertyList;
+}
+
+static RetainPtr<CFDictionaryRef> createPropertyListRep(Archive* archive)
+{
+    RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, &kCFTypeDictionaryValueCallBacks));
+    
+    RetainPtr<CFDictionaryRef> mainResourceDict = createPropertyListRepresentationFromResource(archive->mainResource(), true);
+    if (!mainResourceDict)
+        return 0;
+    CFDictionarySetValue(propertyList.get(), LegacyWebArchiveMainResourceKey, mainResourceDict.get());
+        
+    RetainPtr<CFMutableArrayRef> subresourcesArray(AdoptCF, CFArrayCreateMutable(0, archive->subresources().size(), &kCFTypeArrayCallBacks));
+    const Vector<RefPtr<ArchiveResource> >& subresources(archive->subresources());
+    for (unsigned i = 0; i < subresources.size(); ++i) {
+        RetainPtr<CFDictionaryRef> subresource = createPropertyListRepresentationFromResource(subresources[i].get(), false);
+        if (subresource)
+            CFArrayAppendValue(subresourcesArray.get(), subresource.get());
+        else
+            LOG(Archives, "LegacyWebArchive - Failed to create property list for subresource");
+    }
+    if (CFArrayGetCount(subresourcesArray.get()))
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubresourcesKey, subresourcesArray.get());
+
+    RetainPtr<CFMutableArrayRef> subframesArray(AdoptCF, CFArrayCreateMutable(0, archive->subframeArchives().size(), &kCFTypeArrayCallBacks));
+    const Vector<RefPtr<Archive> >& subframeArchives(archive->subframeArchives());
+    for (unsigned i = 0; i < subframeArchives.size(); ++i) {
+        RetainPtr<CFDictionaryRef> subframeArchive = createPropertyListRep(subframeArchives[i].get());
+        if (subframeArchive)
+            CFArrayAppendValue(subframesArray.get(), subframeArchive.get());
+        else
+            LOG(Archives, "LegacyWebArchive - Failed to create property list for subframe archive");
+    }
+    if (CFArrayGetCount(subframesArray.get()))
+        CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubframeArchivesKey, subframesArray.get());
+
+    return propertyList;
+}
+
+static ResourceResponse createResourceResponseFromPropertyListData(CFDataRef data, CFStringRef responseDataType)
+{
+    ASSERT(data);
+    if (!data)
+        return ResourceResponse();
+    
+    // If the ResourceResponseVersion (passed in as responseDataType) exists at all, this is a "new" webarchive that we can parse well in a cross platform manner
+    // If it doesn't exist, we will assume this is an "old" Cocoa-based WebArchive, and parse the ResourceResponse as such
+    if (!responseDataType)
+        return createResourceResponseFromMacArchivedData(data);
+        
+    // FIXME: Parse the "new" format that the above comment references here
+    return ResourceResponse();
+}
+
+static PassRefPtr<ArchiveResource> createResource(CFDictionaryRef dictionary)
+{
+    ASSERT(dictionary);
+    if (!dictionary)
+        return 0;
+        
+    CFDataRef resourceData = static_cast<CFDataRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceDataKey));
+    if (resourceData && CFGetTypeID(resourceData) != CFDataGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Resource data is not of type CFData, cannot create invalid resource");
+        return 0;
+    }
+    
+    CFStringRef frameName = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceFrameNameKey));
+    if (frameName && CFGetTypeID(frameName) != CFStringGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Frame name is not of type CFString, cannot create invalid resource");
+        return 0;
+    }
+    
+    CFStringRef mimeType = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceMIMETypeKey));
+    if (mimeType && CFGetTypeID(mimeType) != CFStringGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - MIME type is not of type CFString, cannot create invalid resource");
+        return 0;
+    }
+    
+    CFStringRef url = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceURLKey));
+    if (url && CFGetTypeID(url) != CFStringGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - URL is not of type CFString, cannot create invalid resource");
+        return 0;
+    }
+    
+    CFStringRef textEncoding = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceTextEncodingNameKey));
+    if (textEncoding && CFGetTypeID(textEncoding) != CFStringGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Text encoding is not of type CFString, cannot create invalid resource");
+        return 0;
+    }
+
+    ResourceResponse response;
+    
+    CFDataRef resourceResponseData = static_cast<CFDataRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceResponseKey));
+    if (resourceResponseData) {
+        if (CFGetTypeID(resourceResponseData) != CFDataGetTypeID()) {
+            LOG(Archives, "LegacyWebArchive - Resource response data is not of type CFData, cannot create invalid resource");
+            return 0;
+        }
+        
+        CFStringRef resourceResponseVersion = static_cast<CFStringRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveResourceResponseVersionKey));
+        if (resourceResponseVersion && CFGetTypeID(resourceResponseVersion) != CFStringGetTypeID()) {
+            LOG(Archives, "LegacyWebArchive - Resource response version is not of type CFString, cannot create invalid resource");
+            return 0;
+        }
+        
+        response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion);
+    }
+    
+    return ArchiveResource::create(SharedBuffer::create(CFDataGetBytePtr(resourceData), CFDataGetLength(resourceData)), KURL(url), mimeType, textEncoding, frameName, response);
+}
+
+PassRefPtr<LegacyWebArchive> LegacyWebArchive::create()
+{
+    return adoptRef(new LegacyWebArchive);
+}
+
+PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(SharedBuffer* data)
+{
+    LOG(Archives, "LegacyWebArchive - Creating from raw data");
+    
+    RefPtr<LegacyWebArchive> archive = create();
+    if (!archive->init(data))
+        return 0;
+        
+    return archive.release();
+}
+
+PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(PassRefPtr<ArchiveResource> mainResource, Vector<PassRefPtr<ArchiveResource> >& subresources, Vector<PassRefPtr<LegacyWebArchive> >& subframeArchives)
+{
+    ASSERT(mainResource);
+    if (!mainResource)
+        return 0;
+    
+    RefPtr<LegacyWebArchive> archive = create();
+    archive->setMainResource(mainResource);
+    
+    for (unsigned i = 0; i < subresources.size(); ++i)
+        archive->addSubresource(subresources[i]);
+    
+    for (unsigned i = 0; i < subframeArchives.size(); ++i)
+        archive->addSubframeArchive(subframeArchives[i]);  
+        
+    return archive.release();
+}
+
+LegacyWebArchive::LegacyWebArchive()
+{
+}
+
+bool LegacyWebArchive::init(SharedBuffer* data)
+{
+    ASSERT(data);
+    if (!data)
+        return false;
+        
+    RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
+    if (!cfData)
+        return false;
+        
+    CFStringRef errorString = 0;
+    
+    RetainPtr<CFDictionaryRef> plist(AdoptCF, static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(0, cfData.get(), kCFPropertyListImmutable, &errorString)));
+    if (!plist) {
+#ifndef NDEBUG
+        const char* cError = errorString ? CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8) : "unknown error";
+        LOG(Archives, "LegacyWebArchive - Error parsing PropertyList from archive data - %s", cError);
+#endif
+        if (errorString)
+            CFRelease(errorString);
+        return false;
+    }
+    
+    if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Archive property list is not the expected CFDictionary, aborting invalid WebArchive");
+        return false;
+    }
+    
+    return extract(plist.get());
+}
+
+bool LegacyWebArchive::extract(CFDictionaryRef dictionary)
+{
+    ASSERT(dictionary);
+    if (!dictionary) {
+        LOG(Archives, "LegacyWebArchive - Null root CFDictionary, aborting invalid WebArchive");
+        return false;
+    }
+    
+    CFDictionaryRef mainResourceDict = static_cast<CFDictionaryRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveMainResourceKey));
+    if (!mainResourceDict) {
+        LOG(Archives, "LegacyWebArchive - No main resource in archive, aborting invalid WebArchive");
+        return false;
+    }
+    if (CFGetTypeID(mainResourceDict) != CFDictionaryGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Main resource is not the expected CFDictionary, aborting invalid WebArchive");
+        return false;
+    }
+    
+    setMainResource(createResource(mainResourceDict));
+    if (!mainResource()) {
+        LOG(Archives, "LegacyWebArchive - Failed to parse main resource from CFDictionary or main resource does not exist, aborting invalid WebArchive");
+        return false;
+    }
+    
+    CFArrayRef subresourceArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubresourcesKey));
+    if (subresourceArray && CFGetTypeID(subresourceArray) != CFArrayGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Subresources is not the expected Array, aborting invalid WebArchive");
+        return false;
+    }
+    
+    if (subresourceArray) {
+        CFIndex count = CFArrayGetCount(subresourceArray);
+        for (CFIndex i = 0; i < count; ++i) {
+            CFDictionaryRef subresourceDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subresourceArray, i));
+            if (CFGetTypeID(subresourceDict) != CFDictionaryGetTypeID()) {
+                LOG(Archives, "LegacyWebArchive - Subresource is not expected CFDictionary, aborting invalid WebArchive");
+                return false;
+            }
+            addSubresource(createResource(subresourceDict));
+        }
+    }
+    
+    CFArrayRef subframeArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubframeArchivesKey));
+    if (subframeArray && CFGetTypeID(subframeArray) != CFArrayGetTypeID()) {
+        LOG(Archives, "LegacyWebArchive - Subframe archives is not the expected Array, aborting invalid WebArchive");
+        return false;
+    }
+    
+    if (subframeArray) {
+        CFIndex count = CFArrayGetCount(subframeArray);
+        for (CFIndex i = 0; i < count; ++i) {
+            CFDictionaryRef subframeDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subframeArray, i));
+            if (CFGetTypeID(subframeDict) != CFDictionaryGetTypeID()) {
+                LOG(Archives, "LegacyWebArchive - Subframe array is not expected CFDictionary, aborting invalid WebArchive");
+                return false;
+            }
+            
+            RefPtr<LegacyWebArchive> subframeArchive = create();
+            if (subframeArchive->extract(subframeDict))
+                addSubframeArchive(subframeArchive.release());
+            else
+                LOG(Archives, "LegacyWebArchive - Invalid subframe archive skipped");
+        }
+    }
+    
+    return true;
+}
+
+RetainPtr<CFDataRef> LegacyWebArchive::rawDataRepresentation()
+{
+    RetainPtr<CFDictionaryRef> propertyList = createPropertyListRep(this);
+    if (!propertyList) {
+        LOG(Archives, "LegacyWebArchive - Failed to create property list for archive, returning no data");
+        return 0;
+    }
+    
+    // FIXME: On Mac, WebArchives have been written out as Binary Property Lists until this change.
+    // Unless we jump through CFWriteStream hoops, they'll now be textual XML data.  Is this okay?
+    RetainPtr<CFDataRef> plistData(AdoptCF, CFPropertyListCreateXMLData(0, propertyList.get()));
+    if (!plistData) {
+        LOG(Archives, "LegacyWebArchive - Failed to convert property list into raw data, returning no data");
+        return 0;
+    }
+    
+    return plistData;
+}
+
+#if !PLATFORM(MAC)
+// FIXME: Is it possible to parse in a Cocoa-style resource response manually, 
+// without NSKeyed(Un)Archiver, manipulating plists directly?
+// If so, the code that does it will go here.  
+// In the meantime, Mac will continue to NSKeyed(Un)Archive the response as it always has
+ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef responseData)
+{
+    return ResourceResponse();
+}
+
+RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse& response)
+{
+    // FIXME: Write out the "new" format described in ::createResourceResponseFromPropertyListData() up above
+    return 0;
+}
+#endif
+
+}
index c155198..eff4534 100644 (file)
 #ifndef LegacyWebArchive_h
 #define LegacyWebArchive_h
 
-// FIXME:  Code will go here!
+#include "Archive.h"
+
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+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);
+
+    RetainPtr<CFDataRef> rawDataRepresentation();
+
+private:
+    LegacyWebArchive();
+    bool init(SharedBuffer*);
+    bool extract(CFDictionaryRef);
+    
+};
+
+ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef);
+RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse&);
+
+}
 
 #endif // Archive
index 7aab54f..8da6148 100644 (file)
 #include "config.h"
 #include "LegacyWebArchive.h"
 
-// FIXME:  Code will go here!
+namespace WebCore {
+
+static const NSString *LegacyWebArchiveResourceResponseKey = @"WebResourceResponse";
+
+// FIXME: Is it possible to parse in a Cocoa-style resource response manually, 
+// without NSKeyed(Un)Archiver, manipulating plists directly?
+ResourceResponse createResourceResponseFromMacArchivedData(CFDataRef responseData)
+{    
+    ASSERT(responseData);
+    if (!responseData)
+        return ResourceResponse();
+    
+    NSURLResponse *response;
+    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)responseData];
+    @try {
+        id responseObject = [unarchiver decodeObjectForKey:LegacyWebArchiveResourceResponseKey];
+        if ([responseObject isKindOfClass:[NSURLResponse class]])
+            response = responseObject;
+        [unarchiver finishDecoding];
+    } @catch(id) {
+        response = nil;
+    }
+    [unarchiver release];
+    
+    return ResourceResponse(response);
+}
+
+RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse& response)
+{    
+    NSURLResponse *nsResponse = response.nsURLResponse();
+    if (!nsResponse)
+        return 0;
+        
+    NSMutableData *responseData = (NSMutableData *)CFDataCreateMutable(0, 0);
+    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:responseData];
+    [archiver encodeObject:nsResponse forKey:LegacyWebArchiveResourceResponseKey];
+    [archiver finishEncoding];
+    [archiver release];
+    
+    return RetainPtr<CFDataRef>(AdoptCF, (CFDataRef)responseData);
+}
+
+}
index 6d8cb6d..9ee1083 100644 (file)
@@ -66,6 +66,7 @@ namespace WebCore {
             : ResourceRequestBase()
             , m_nsRequest(nsRequest) { }
         
+        void applyWebArchiveHackForMail();
         NSURLRequest* nsURLRequest() const;
 
     private:
index 6735024..36aa128 100644 (file)
@@ -101,4 +101,10 @@ void ResourceRequest::doUpdatePlatformRequest()
     m_nsRequest.adoptNS(nsRequest);
 }
 
+void ResourceRequest::applyWebArchiveHackForMail()
+{
+    // Hack because Mail checks for this property to detect data / archive loads
+    [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)nsURLRequest()];
+}
+
 }
index a18590c..4758fc0 100644 (file)
@@ -1,3 +1,11 @@
+2008-03-25  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Darin
+
+        <rdar://problem/4516169> - Support WebArchives on Windows
+
+        * WebKit.xcodeproj/project.pbxproj:
+
 2008-03-24  Brady Eidson  <beidson@apple.com>
 
         Reviewed by Darin's rubberstamp
index 0eda743..498bb50 100644 (file)
@@ -63,8 +63,6 @@
                5DE92FEF0BD7017E0059A5FD /* WebAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DE92FEE0BD7017E0059A5FD /* WebAssertions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5DF7B1D10D161FD00062CD32 /* WebNetscapePlugInStreamLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DF7B1CF0D161FCF0062CD32 /* WebNetscapePlugInStreamLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5DF7B1D20D161FD00062CD32 /* WebNetscapePlugInStreamLoaderClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7B1D00D161FD00062CD32 /* WebNetscapePlugInStreamLoaderClient.mm */; };
-               650F74E409E488F70020118A /* WebUnarchivingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 650F74E209E488F70020118A /* WebUnarchivingState.h */; };
-               650F74E509E488F70020118A /* WebUnarchivingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 650F74E309E488F70020118A /* WebUnarchivingState.m */; };
                65488DA1084FBCCB00831AD0 /* WebNSDictionaryExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 65488D9F084FBCCB00831AD0 /* WebNSDictionaryExtras.h */; };
                65488DA2084FBCCB00831AD0 /* WebNSDictionaryExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 65488DA0084FBCCB00831AD0 /* WebNSDictionaryExtras.m */; };
                6550B7C7099EFAE90090D781 /* WebArchiver.h in Headers */ = {isa = PBXBuildFile; fileRef = 6550B7C5099EFAE90090D781 /* WebArchiver.h */; };
                5DE92FEE0BD7017E0059A5FD /* WebAssertions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebAssertions.h; sourceTree = "<group>"; };
                5DF7B1CF0D161FCF0062CD32 /* WebNetscapePlugInStreamLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNetscapePlugInStreamLoaderClient.h; sourceTree = "<group>"; };
                5DF7B1D00D161FD00062CD32 /* WebNetscapePlugInStreamLoaderClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNetscapePlugInStreamLoaderClient.mm; sourceTree = "<group>"; };
-               650F74E209E488F70020118A /* WebUnarchivingState.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebUnarchivingState.h; sourceTree = "<group>"; };
-               650F74E309E488F70020118A /* WebUnarchivingState.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = WebUnarchivingState.m; sourceTree = "<group>"; };
                65488D9F084FBCCB00831AD0 /* WebNSDictionaryExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSDictionaryExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                65488DA0084FBCCB00831AD0 /* WebNSDictionaryExtras.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebNSDictionaryExtras.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                6550B7C5099EFAE90090D781 /* WebArchiver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebArchiver.h; sourceTree = "<group>"; };
                                C0167BF70D7F5DD00028696E /* WebScriptDebugger.mm */,
                                515E27CC0458C86500CA2D3A /* WebUIDelegate.h */,
                                65A7D44A0568AB2600E70EF6 /* WebUIDelegatePrivate.h */,
-                               650F74E209E488F70020118A /* WebUnarchivingState.h */,
                                51A8B579042834F700CA2D3A /* WebView.h */,
                                930D02BB06275F640076701E /* WebViewInternal.h */,
                                51A8B57D0428353A00CA2D3A /* WebViewPrivate.h */,
                                F5AEBB3D024A527601C1A526 /* WebPreferences.m */,
                                84311A1305EAAAF00088EDA4 /* WebResource.mm */,
                                7E6FEF0608985A7200C44C3F /* WebScriptDebugDelegate.mm */,
-                               650F74E309E488F70020118A /* WebUnarchivingState.m */,
                                51A8B57A042834F700CA2D3A /* WebView.mm */,
                        );
                        name = WebView;
                                939810750824BF01008DF038 /* WebUIDelegate.h in Headers */,
                                939810830824BF01008DF038 /* WebUIDelegatePrivate.h in Headers */,
                                939810150824BF01008DF038 /* WebURLsWithTitles.h in Headers */,
-                               650F74E409E488F70020118A /* WebUnarchivingState.h in Headers */,
                                939810700824BF01008DF038 /* WebView.h in Headers */,
                                939810460824BF01008DF038 /* WebViewFactory.h in Headers */,
                                9398109B0824BF01008DF038 /* WebViewInternal.h in Headers */,
                                939810CC0824BF01008DF038 /* WebStringTruncator.m in Sources */,
                                93EB178D09F88D460091F8FF /* WebSystemInterface.m in Sources */,
                                939810BE0824BF01008DF038 /* WebURLsWithTitles.m in Sources */,
-                               650F74E509E488F70020118A /* WebUnarchivingState.m in Sources */,
                                939811070824BF01008DF038 /* WebView.mm in Sources */,
                                939810E80824BF01008DF038 /* WebViewFactory.mm in Sources */,
                                939810DD0824BF01008DF038 /* npapi.m in Sources */,
index b62895c..43d79dc 100644 (file)
@@ -1,3 +1,91 @@
+2008-03-25  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Darin
+
+        <rdar://problem/4516169> - Support WebArchives on Windows
+        And paves the way for many future WebArchive bug fixes and enhancements
+
+        This change moves most of the real workhorse code about WebArchives into WebCore.  It maintains 
+        1-to-1 relationships between a few objects in WebCore and WebKit.  Such as:
+         * WebArchive <-> LegacyWebArchive
+         * WebResource <-> ArchiveResource
+         * WebUnarchivingState <-> ArchiveResourceCollection
+        The other biggest changes involve many FrameLoaderClient methods that existed soley for WebArchives 
+        and now exist in WebCore
+
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        (WebFrameLoaderClient::clearUnarchivingState): Emptied - to be removed in a followup patch
+        (WebFrameLoaderClient::finalSetupForReplace):
+        (WebFrameLoaderClient::setDefersLoading):
+        (WebFrameLoaderClient::willUseArchive):
+        (WebFrameLoaderClient::isArchiveLoadPending):
+        (WebFrameLoaderClient::cancelPendingArchiveLoad):
+        (WebFrameLoaderClient::clearArchivedResources):
+        (WebFrameLoaderClient::createFrame):
+
+        * WebView/WebArchive.mm:
+        (+[WebArchivePrivate initialize]):
+        (-[WebArchivePrivate init]):
+        (-[WebArchivePrivate initWithCoreArchive:]):
+        (-[WebArchivePrivate coreArchive]):
+        (-[WebArchivePrivate setCoreArchive:]):
+        (-[WebArchivePrivate dealloc]):
+        (-[WebArchivePrivate finalize]):
+        (-[WebArchive init]):
+        (-[WebArchive initWithMainResource:subresources:subframeArchives:]):
+        (-[WebArchive initWithData:]):
+        (-[WebArchive initWithCoder:]):
+        (-[WebArchive encodeWithCoder:]):
+        (-[WebArchive mainResource]):
+        (-[WebArchive subresources]):
+        (-[WebArchive subframeArchives]):
+        (-[WebArchive data]):
+        (-[WebArchive _initWithCoreLegacyWebArchive:WebCore::]):
+        (-[WebArchive WebCore::]):
+        * WebView/WebArchiveInternal.h: Added.
+
+        * WebView/WebDataSource.mm:
+        (-[WebDataSourcePrivate dealloc]):
+        (-[WebDataSource _addSubframeArchives:]):
+        (-[WebDataSource _documentFragmentWithArchive:]):
+        (-[WebDataSource subresourceForURL:]):
+        (-[WebDataSource addSubresource:]):
+        * WebView/WebDataSourceInternal.h:
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame loadArchive:]):
+        * WebView/WebFrameInternal.h:
+
+        * WebView/WebHTMLRepresentation.mm:
+        (-[WebHTMLRepresentation finishedLoadingWithDataSource:]):
+
+        * WebView/WebResource.mm:
+        (+[WebResourcePrivate initialize]):
+        (-[WebResourcePrivate init]):
+        (-[WebResourcePrivate initWithCoreResource:]):
+        (-[WebResourcePrivate dealloc]):
+        (-[WebResourcePrivate finalize]):
+        (-[WebResource initWithCoder:]):
+        (-[WebResource encodeWithCoder:]):
+        (-[WebResource data]):
+        (-[WebResource URL]):
+        (-[WebResource MIMEType]):
+        (-[WebResource textEncodingName]):
+        (-[WebResource frameName]):
+        (-[WebResource _initWithCoreResource:WebCore::]):
+        (-[WebResource WebCore::]):
+        (-[WebResource _ignoreWhenUnarchiving]):
+        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
+        (-[WebResource _fileWrapperRepresentation]):
+        (-[WebResource _response]):
+        (-[WebResource _stringValue]):
+        * WebView/WebResourceInternal.h: Added.
+        * WebView/WebResourcePrivate.h:
+
+        * WebView/WebUnarchivingState.h: Removed.
+        * WebView/WebUnarchivingState.m: Removed.
+
 2008-03-24  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by Mark Rowe.
index a1709e5..ae30c65 100644 (file)
@@ -654,7 +654,6 @@ void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const Re
 
 void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader)
 {
-    [dataSource(loader) _clearUnarchivingState];
 }
 
 void WebFrameLoaderClient::willChangeEstimatedProgress()
@@ -721,7 +720,6 @@ void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
 
 void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
 {
-    [dataSource(loader) _clearUnarchivingState];
 }
 
 void WebFrameLoaderClient::updateGlobalHistory(const KURL& url)
@@ -779,44 +777,24 @@ bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
 
 void WebFrameLoaderClient::setDefersLoading(bool defers)
 {
-    if (!defers)
-        deliverArchivedResourcesAfterDelay();
 }
 
 bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
 {
-    if (request.url() != originalURL)
-        return false;
-
-    WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL];
-    if (!resource)
-        return false;
-
-    m_pendingArchivedResources.set(loader, resource);
-    // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
-    deliverArchivedResourcesAfterDelay();
-
-    return true;
+    return false;
 }
 
 bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const
 {
-    return m_pendingArchivedResources.contains(loader);
+    return false;
 }
 
 void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader)
 {
-    if (m_pendingArchivedResources.isEmpty())
-        return;
-    m_pendingArchivedResources.remove(loader);
-    if (m_pendingArchivedResources.isEmpty())
-        m_archivedResourcesDeliveryTimer.stop();
 }
 
 void WebFrameLoaderClient::clearArchivedResources()
 {
-    m_pendingArchivedResources.clear();
-    m_archivedResourcesDeliveryTimer.stop();
 }
 
 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
@@ -1147,7 +1125,7 @@ PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const Strin
     if ([newFrame _dataSource])
         [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding());  
 
-    [m_webFrame.get() _loadURL:url referrer:referrer intoChild:newFrame];
+    core(m_webFrame.get())->loader()->loadURLIntoChildFrame(url, referrer, newCoreFrame.get());
 
     // The frame's onload handler may have removed it from the document.
     if (!newCoreFrame->tree()->parent())
index bb4bd59..633db4f 100644 (file)
  */
 
 #import "WebArchive.h"
+#import "WebArchiveInternal.h"
 
 #import "WebKitLogging.h"
+#import "WebResourceInternal.h"
 #import "WebResourcePrivate.h"
 #import "WebTypesInternal.h"
 
+#import <WebCore/ArchiveResource.h>
+#import <WebCore/LegacyWebArchive.h>
+#import <WebCore/WebCoreObjCExtras.h>
+
+using namespace WebCore;
+
 NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type";
 
 static NSString * const WebMainResourceKey = @"WebMainResource";
@@ -40,25 +48,96 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives";
 
 @interface WebArchivePrivate : NSObject
 {
-    @public
-    WebResource *mainResource;
-    NSArray *subresources;
-    NSArray *subframeArchives;
+@public
+    WebResource *cachedMainResource;
+    NSArray *cachedSubresources;
+    NSArray *cachedSubframeArchives;
+@private
+    LegacyWebArchive* coreArchive;
 }
+
+- (id)initWithCoreArchive:(PassRefPtr<LegacyWebArchive>)coreArchive;
+- (LegacyWebArchive*)coreArchive;
+- (void)setCoreArchive:(PassRefPtr<LegacyWebArchive>)newCoreArchive;
 @end
 
 @implementation WebArchivePrivate
 
+#ifndef BUILDING_ON_TIGER
++ (void)initialize
+{
+    WebCoreObjCFinalizeOnMainThread(self);
+}
+#endif
+
+- (id)init
+{
+    self = [super init];
+    if (self)
+        coreArchive = LegacyWebArchive::create().releaseRef();
+    return self;
+}
+
+- (id)initWithCoreArchive:(PassRefPtr<LegacyWebArchive>)_coreArchive
+{
+    self = [super init];
+    if (!self || !_coreArchive) {
+        [self release];
+        return nil;
+    }
+    
+    coreArchive = _coreArchive.releaseRef();
+    
+    return self;
+}
+
+- (LegacyWebArchive*)coreArchive
+{
+    return coreArchive;
+}
+
+- (void)setCoreArchive:(PassRefPtr<LegacyWebArchive>)newCoreArchive
+{
+    ASSERT(coreArchive);
+    ASSERT(newCoreArchive);
+    coreArchive = newCoreArchive.releaseRef();
+}
+
 - (void)dealloc
 {
-    [mainResource release];
-    [subresources release];
-    [subframeArchives release];
+    ASSERT(coreArchive);
+    coreArchive->deref();
+    coreArchive = 0;
+    
+    [cachedMainResource release];
+    [cachedSubresources release];
+    [cachedSubframeArchives release];
+    
     [super dealloc];
 }
 
+- (void)finalize
+{
+    ASSERT(coreArchive);
+    coreArchive->deref();
+    coreArchive = 0;
+    
+    [super finalize];
+}
+
 @end
 
+@implementation WebArchive
+
+- (id)init
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    _private = [[WebArchivePrivate alloc] init];
+    return self;
+}
+
 static BOOL isArrayOfClass(id object, Class elementClass)
 {
     if (![object isKindOfClass:[NSArray class]])
@@ -71,121 +150,108 @@ static BOOL isArrayOfClass(id object, Class elementClass)
     return YES;
 }
 
-@implementation WebArchive
-
-- (id)init
+- (id)initWithMainResource:(WebResource *)mainResource subresources:(NSArray *)subresources subframeArchives:(NSArray *)subframeArchives
 {
     self = [super init];
     if (!self)
         return nil;
+
     _private = [[WebArchivePrivate alloc] init];
-    return self;
-}
 
-- (id)initWithMainResource:(WebResource *)mainResource subresources:(NSArray *)subresources subframeArchives:(NSArray *)subframeArchives
-{
-    self = [self init];
-    if (!self)
+    _private->cachedMainResource = [mainResource retain];
+    if (!_private->cachedMainResource) {
+        [self release];
         return nil;
+    }
     
-    _private->mainResource = [mainResource retain];
-    _private->subresources = [subresources retain];
-    _private->subframeArchives = [subframeArchives retain];
-    
-    if (!_private->mainResource) {
+    if (!subresources || isArrayOfClass(subresources, [WebResource class]))
+        _private->cachedSubresources = [subresources retain];
+    else {
         [self release];
         return nil;
     }
-    
-    return self;
-}
 
-- (id)_initWithPropertyList:(id)propertyList
-{
-    self = [self init];
-    if (!self)
-        return nil;
-    
-    if (![propertyList isKindOfClass:[NSDictionary class]]) {
+    if (!subframeArchives || isArrayOfClass(subframeArchives, [WebArchive class]))
+        _private->cachedSubframeArchives = [subframeArchives retain];
+    else {
         [self release];
         return nil;
     }
     
-    _private->mainResource = [[WebResource alloc] _initWithPropertyList:[propertyList objectForKey:WebMainResourceKey]];    
-    if (!_private->mainResource) {
+    RefPtr<ArchiveResource> coreMainResource = mainResource ? [mainResource _coreResource] : 0;
+
+    Vector<PassRefPtr<ArchiveResource> > coreResources;
+    NSEnumerator *enumerator = [subresources objectEnumerator];
+    WebResource *subresource;
+    while ((subresource = [enumerator nextObject]) != nil)
+        coreResources.append([subresource _coreResource]);
+
+    Vector<PassRefPtr<LegacyWebArchive> > coreArchives;
+    enumerator = [subframeArchives objectEnumerator];
+    WebArchive *subframeArchive;
+    while ((subframeArchive = [enumerator nextObject]) != nil)
+        coreArchives.append([subframeArchive->_private coreArchive]);
+
+    [_private setCoreArchive:LegacyWebArchive::create(coreMainResource.release(), coreResources, coreArchives)];
+    if (![_private coreArchive]) {
         [self release];
         return nil;
     }
-    
-    _private->subresources = [[WebResource _resourcesFromPropertyLists:[propertyList objectForKey:WebSubresourcesKey]] retain];
-    
-    NSEnumerator *enumerator = [[propertyList objectForKey:WebSubframeArchivesKey] objectEnumerator];
-    NSMutableArray *subframeArchives = [[NSMutableArray alloc] init];
-    NSDictionary *archivePropertyList;
-    while ((archivePropertyList = [enumerator nextObject]) != nil) {
-        WebArchive *archive = [[WebArchive alloc] _initWithPropertyList:archivePropertyList];
-        if (archive) {
-            [subframeArchives addObject:archive];
-            [archive release];
-        }
-    }
-    _private->subframeArchives = subframeArchives;
 
     return self;
 }
 
 - (id)initWithData:(NSData *)data
 {
+    self = [super init];
+    if (!self)
+        return nil;
+        
 #if !LOG_DISABLED
     CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
 #endif
-    NSDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:data 
-                                                                  mutabilityOption:NSPropertyListImmutable 
-                                                                            format:nil
-                                                                  errorDescription:nil];
+
+    _private = [[WebArchivePrivate alloc] init];
+    [_private setCoreArchive:LegacyWebArchive::create(SharedBuffer::wrapNSData(data).get())];
+        
 #if !LOG_DISABLED
     CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
     CFAbsoluteTime duration = end - start;
 #endif
     LOG(Timing, "Parsing web archive with [NSPropertyListSerialization propertyListFromData::::] took %f seconds", duration);
     
-    return [self _initWithPropertyList:propertyList];
+    return self;
 }
 
 - (id)initWithCoder:(NSCoder *)decoder
 {    
-    self = [self init];
-    if (!self)
-        return nil;
-
+    WebResource *mainResource = nil;
+    NSArray *subresources = nil;
+    NSArray *subframeArchives = nil;
+    
     @try {
         id object = [decoder decodeObjectForKey:WebMainResourceKey];
         if ([object isKindOfClass:[WebResource class]])
-            _private->mainResource = [object retain];
+            mainResource = [object retain];
         object = [decoder decodeObjectForKey:WebSubresourcesKey];
         if (isArrayOfClass(object, [WebResource class]))
-            _private->subresources = [object retain];
+            subresources = [object retain];
         object = [decoder decodeObjectForKey:WebSubframeArchivesKey];
         if (isArrayOfClass(object, [WebArchive class]))
-            _private->subframeArchives = [object retain];
+            subframeArchives = [object retain];
     } @catch(id) {
         [self release];
         return nil;
     }
 
-    if (!_private->mainResource) {
-        [self release];
-        return nil;
-    }
-
-    return self;
+    return [self initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives];
 }
 
 - (void)encodeWithCoder:(NSCoder *)encoder
 {
-    [encoder encodeObject:_private->mainResource forKey:WebMainResourceKey];
-    [encoder encodeObject:_private->subresources forKey:WebSubresourcesKey];
-    [encoder encodeObject:_private->subframeArchives forKey:WebSubframeArchivesKey];    
+    [encoder encodeObject:[self mainResource] forKey:WebMainResourceKey];
+    [encoder encodeObject:[self subresources] forKey:WebSubresourcesKey];
+    [encoder encodeObject:[self subframeArchives] forKey:WebSubframeArchivesKey];    
 }
 
 - (void)dealloc
@@ -201,55 +267,100 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (WebResource *)mainResource
 {
-    return [[_private->mainResource retain] autorelease];
+    // Currently from WebKit API perspective, WebArchives are entirely immutable once created
+    // If they ever become mutable, we'll need to rethink this. 
+    if (!_private->cachedMainResource) {
+        LegacyWebArchive* coreArchive = [_private coreArchive];
+        if (coreArchive)
+            _private->cachedMainResource = [[WebResource alloc] _initWithCoreResource:coreArchive->mainResource()];
+    }
+    
+    return [[_private->cachedMainResource retain] autorelease];
 }
 
 - (NSArray *)subresources
 {
-    return [[_private->subresources retain] autorelease];
+    // Currently from WebKit API perspective, WebArchives are entirely immutable once created
+    // If they ever become mutable, we'll need to rethink this.     
+    if (!_private->cachedSubresources) {
+        LegacyWebArchive* coreArchive = [_private coreArchive];
+        if (!coreArchive)
+            _private->cachedSubresources = [[NSArray alloc] init];
+        else {
+            const Vector<RefPtr<ArchiveResource> >& subresources(coreArchive->subresources());
+            NSMutableArray *mutableArray = _private->cachedSubresources = [[NSMutableArray alloc] initWithCapacity:subresources.size()];
+            for (unsigned i = 0; i < subresources.size(); ++i) {
+                WebResource *resource = [[WebResource alloc] _initWithCoreResource:subresources[i].get()];
+                [mutableArray addObject:resource];
+                [resource release];
+            }
+        }
+    }
+    
+    return [[_private->cachedSubresources retain] autorelease];
 }
 
 - (NSArray *)subframeArchives
 {
-    return [[_private->subframeArchives retain] autorelease];
-}
-
-- (NSDictionary *)_propertyListRepresentation
-{
-    NSMutableDictionary *propertyList = [NSMutableDictionary dictionary];
-    if (_private->mainResource) {
-        [propertyList setObject:[_private->mainResource _propertyListRepresentation] forKey:WebMainResourceKey];
-    }
-    NSArray *propertyLists = [WebResource _propertyListsFromResources:_private->subresources];
-    if ([propertyLists count] > 0) {
-        [propertyList setObject:propertyLists forKey:WebSubresourcesKey];
-    }
-    NSEnumerator *enumerator = [_private->subframeArchives objectEnumerator];
-    NSMutableArray *subarchivePropertyLists = [[NSMutableArray alloc] init];
-    WebArchive *archive;
-    while ((archive = [enumerator nextObject]) != nil) {
-        [subarchivePropertyLists addObject:[archive _propertyListRepresentation]];
-    }
-    if ([subarchivePropertyLists count] > 0) {
-        [propertyList setObject:subarchivePropertyLists forKey:WebSubframeArchivesKey];
+    // Currently from WebKit API perspective, WebArchives are entirely immutable once created
+    // If they ever become mutable, we'll need to rethink this.  
+    if (!_private->cachedSubframeArchives) {
+        LegacyWebArchive* coreArchive = [_private coreArchive];
+        if (!coreArchive)
+            _private->cachedSubframeArchives = [[NSArray alloc] init];
+        else {
+            const Vector<RefPtr<Archive> >& subframeArchives(coreArchive->subframeArchives());
+            NSMutableArray *mutableArray = _private->cachedSubframeArchives = [[NSMutableArray alloc] initWithCapacity:subframeArchives.size()];
+            for (unsigned i = 0; i < subframeArchives.size(); ++i) {
+                WebArchive *archive = [[WebArchive alloc] _initWithCoreLegacyWebArchive:(LegacyWebArchive *)subframeArchives[i].get()];
+                [mutableArray addObject:archive];
+                [archive release];
+            }
+        }
     }
-    [subarchivePropertyLists release];
-    return propertyList;
+    
+    return [[_private->cachedSubframeArchives retain] autorelease];
 }
 
 - (NSData *)data
 {
-    NSDictionary *propertyList = [self _propertyListRepresentation];
 #if !LOG_DISABLED
     CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
 #endif
-    NSData *data = [NSPropertyListSerialization dataFromPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
+
+    RetainPtr<CFDataRef> data = [_private coreArchive]->rawDataRepresentation();
+    
 #if !LOG_DISABLED
     CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
     CFAbsoluteTime duration = end - start;
 #endif
-    LOG(Timing, "Serializing web archive with [NSPropertyListSerialization dataFromPropertyList:::] took %f seconds", duration);
-    return data;
+    LOG(Timing, "Serializing web archive to raw CFPropertyList data took %f seconds", duration);
+        
+    return [[(NSData *)data.get() retain] autorelease];
+}
+
+@end
+
+@implementation WebArchive (WebInternal)
+
+- (id)_initWithCoreLegacyWebArchive:(PassRefPtr<WebCore::LegacyWebArchive>)coreLegacyWebArchive
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    
+    _private = [[WebArchivePrivate alloc] initWithCoreArchive:coreLegacyWebArchive];
+    if (!_private) {
+        [self release];
+        return nil;
+    }
+
+    return self;
+}
+
+- (WebCore::LegacyWebArchive *)_coreLegacyWebArchive
+{
+    return [_private coreArchive];
 }
 
 @end
similarity index 74%
rename from WebKit/mac/WebView/WebUnarchivingState.h
rename to WebKit/mac/WebView/WebArchiveInternal.h
index 84d808b..071d4ab 100644 (file)
@@ -1,18 +1,18 @@
 /*
- * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ * 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. 
+ *     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. 
+ *     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. 
+ *     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
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <Foundation/Foundation.h>
+#import "WebArchive.h"
+#import <JavaScriptCore/Forward.h>
 
-@class WebArchive;
-@class WebResource;
-
-@interface WebUnarchivingState : NSObject
-{
-    NSMutableDictionary *archivedSubframes;
-    NSMutableDictionary *archivedResources;
+namespace WebCore {
+    class LegacyWebArchive;
 }
 
-- (void)addArchive:(WebArchive *)archive;
-- (void)addResource:(WebResource *)resource;
-- (WebResource *)archivedResourceForURL:(NSURL *)URL;
-- (WebArchive *)popSubframeArchiveWithFrameName:(NSString *)frameName;
+@interface WebArchive (WebInternal)
+
+- (id)_initWithCoreLegacyWebArchive:(WTF::PassRefPtr<WebCore::LegacyWebArchive>)coreLegacyWebArchive;
+- (WebCore::LegacyWebArchive *)_coreLegacyWebArchive;
 
 @end
index a39c943..bf6f2d9 100644 (file)
@@ -29,6 +29,7 @@
 #import "WebDataSource.h"
 
 #import "WebArchive.h"
+#import "WebArchiveInternal.h"
 #import "WebArchiver.h"
 #import "WebDataSourceInternal.h"
 #import "WebDocument.h"
 #import "WebNSURLExtras.h"
 #import "WebNSURLRequestExtras.h"
 #import "WebPDFRepresentation.h"
+#import "WebResourceInternal.h"
 #import "WebResourceLoadDelegate.h"
 #import "WebResourcePrivate.h"
-#import "WebUnarchivingState.h"
 #import "WebViewInternal.h"
 #import <JavaScriptCore/Assertions.h>
 #import <WebCore/FrameLoader.h>
 #import <WebCore/KURL.h>
+#import <WebCore/LegacyWebArchive.h>
 #import <WebCore/MIMETypeRegistry.h>
 #import <WebCore/ResourceRequest.h>
 #import <WebCore/SharedBuffer.h>
@@ -66,7 +68,6 @@ using namespace WebCore;
    
     id <WebDocumentRepresentation> representation;
     
-    WebUnarchivingState *unarchivingState;
     BOOL representationFinishedLoading;
 }
 @end
@@ -87,7 +88,6 @@ using namespace WebCore;
     loader->deref();
     
     [representation release];
-    [unarchivingState release];
 
     [super dealloc];
 }
@@ -145,10 +145,14 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
 
 - (void)_addSubframeArchives:(NSArray *)subframeArchives
 {
+    // FIXME: This SPI is poor, poor design.  Can we come up with another solution for those who need it?
+    DocumentLoader* loader = [self _documentLoader];
+    ASSERT(loader);
+    
     NSEnumerator *enumerator = [subframeArchives objectEnumerator];
     WebArchive *archive;
     while ((archive = [enumerator nextObject]) != nil)
-        [self _addToUnarchiveState:archive];
+        loader->addAllArchiveResources([archive _coreLegacyWebArchive]);
 }
 
 - (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
@@ -204,12 +208,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
     }
 }
 
-- (void)_clearUnarchivingState
-{
-    [_private->unarchivingState release];
-    _private->unarchivingState = nil;
-}
-
 - (void)_revertToProvisionalState
 {
     [self _setRepresentation:nil];
@@ -238,11 +236,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
     return repTypes;
 }
 
-- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
-{
-    return [_private->unarchivingState archivedResourceForURL:URL];
-}
-
 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
 {
     DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
@@ -250,6 +243,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
         [[self webFrame] _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
 }
 
+// FIXME: There are few reasons why this method and many of its related methods can't be pushed entirely into WebCore in the future.
 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
 {
     ASSERT(archive);
@@ -259,7 +253,9 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
         if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
             NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
             // FIXME: seems poor form to do this as a side effect of getting a document fragment
-            [self _addToUnarchiveState:archive];
+            if (DocumentLoader* loader = [self _documentLoader])
+                loader->addAllArchiveResources([archive _coreLegacyWebArchive]);
+
             DOMDocumentFragment *fragment = [[self webFrame] _documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
             [markupString release];
             return fragment;
@@ -306,11 +302,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
     return url;
 }
 
-- (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
-{
-    return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
-}
-
 - (WebView *)_webView
 {
     return [[self webFrame] webView];
@@ -336,13 +327,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
     [_private->representation setDataSource:self];
 }
 
-- (void)_addToUnarchiveState:(WebArchive *)archive
-{
-    if (!_private->unarchivingState)
-        _private->unarchivingState = [[WebUnarchivingState alloc] init];
-    [_private->unarchivingState addArchive:archive];
-}
-
 - (DocumentLoader*)_documentLoader
 {
     return _private->loader;
@@ -503,19 +487,18 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl
 
     NSData *data;
     NSURLResponse *response;
-    if (![[self webFrame] _getData:&data andResponse:&response forURL:[URL _web_originalDataAsString]])
-        return [self _archivedSubresourceForURL:URL];
+    if (![[self webFrame] _getData:&data andResponse:&response forURL:[URL _web_originalDataAsString]]) {
+        DocumentLoader* loader = [self _documentLoader];
+        ArchiveResource* coreResource = loader->archiveResourceForURL(URL);
+        return coreResource ? [[[WebResource alloc] _initWithCoreResource:coreResource] autorelease] : nil;
+    }
 
     return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
 }
 
 - (void)addSubresource:(WebResource *)subresource
-{
-    if (subresource) {
-        if (!_private->unarchivingState)
-            _private->unarchivingState = [[WebUnarchivingState alloc] init];
-        [_private->unarchivingState addResource:subresource];
-    }
+{    
+    _private->loader->addArchiveResource([subresource _coreResource]);
 }
 
 @end
index 8caad1b..8779e40 100644 (file)
@@ -48,23 +48,19 @@ class WebDocumentLoaderMac;
 @protocol WebDocumentRepresentation;
 
 @interface WebDataSource (WebInternal)
-- (void)_addToUnarchiveState:(WebArchive *)archive;
 - (void)_makeRepresentation;
 - (BOOL)_isDocumentHTML;
 - (WebView *)_webView;
-- (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName;
 - (NSURL *)_URL;
 - (DOMElement *)_imageElementWithImageResource:(WebResource *)resource;
 - (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource;
 - (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive;
 + (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission;
 - (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement;
-- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL;
 - (id)_initWithDocumentLoader:(WebDocumentLoaderMac*)loader;
 - (void)_finishedLoading;
 - (void)_receivedData:(NSData *)data;
 - (void)_revertToProvisionalState;
 - (void)_setMainDocumentError:(NSError *)error;
-- (void)_clearUnarchivingState;
 - (WebCoreDocumentLoader*)_documentLoader;
 @end
index e9efbaf..b18bccb 100644 (file)
@@ -35,6 +35,7 @@
 #import "DOMHTMLElementInternal.h"
 #import "DOMNodeInternal.h"
 #import "DOMRangeInternal.h"
+#import "WebArchiveInternal.h"
 #import "WebChromeClient.h"
 #import "WebDataSourceInternal.h"
 #import "WebDocumentLoaderMac.h"
@@ -59,6 +60,7 @@
 #import <WebCore/HTMLFrameOwnerElement.h>
 #import <WebCore/HistoryItem.h>
 #import <WebCore/HitTestResult.h>
+#import <WebCore/LegacyWebArchive.h>
 #import <WebCore/Page.h>
 #import <WebCore/PluginData.h>
 #import <WebCore/RenderView.h>
@@ -293,53 +295,6 @@ WebView *getWebView(WebFrame *webFrame)
     return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
 }
 
-/*
-    In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.  
-    The item that was the target of the user's navigation is designated as the "targetItem".  
-    When this method is called with doClip=YES we're able to create the whole tree except for the target's children, 
-    which will be loaded in the future.  That part of the tree will be filled out as the child loads are committed.
-*/
-
-- (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
-{
-    ASSERT(childFrame);
-    HistoryItem* parentItem = _private->coreFrame->loader()->currentHistoryItem();
-    FrameLoadType loadType = _private->coreFrame->loader()->loadType();
-    FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
-
-    // If we're moving in the backforward list, we might want to replace the content
-    // of this child frame with whatever was there at that point.
-    // Reload will maintain the frame contents, LoadSame will not.
-    if (parentItem && parentItem->children().size() &&
-        (isBackForwardLoadType(loadType)
-         || loadType == FrameLoadTypeReloadAllowingStaleData))
-    {
-        HistoryItem* childItem = parentItem->childItemWithName([childFrame name]);
-        if (childItem) {
-            // Use the original URL to ensure we get all the side-effects, such as
-            // onLoad handlers, of any redirects that happened. An example of where
-            // this is needed is Radar 3213556.
-            URL = [NSURL _web_URLWithDataAsString:childItem->originalURLString()];
-            // These behaviors implied by these loadTypes should apply to the child frames
-            childLoadType = loadType;
-
-            if (isBackForwardLoadType(loadType)) {
-                // For back/forward, remember this item so we can traverse any child items as child frames load
-                childFrame->_private->coreFrame->loader()->setProvisionalHistoryItem(childItem);
-            } else {
-                // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
-                childFrame->_private->coreFrame->loader()->setCurrentHistoryItem(childItem);
-            }
-        }
-    }
-
-    WebArchive *archive = [[self _dataSource] _popSubframeArchiveWithName:[childFrame name]];
-    if (archive)
-        [childFrame loadArchive:archive];
-    else
-        childFrame->_private->coreFrame->loader()->load([URL absoluteURL], referrer, childLoadType, String(), 0, 0);
-}
-
 - (void)_attachScriptDebugger
 {
     if (_private->scriptDebugger)
@@ -1311,20 +1266,8 @@ static NSURL *createUniqueWebDataURL()
 
 - (void)loadArchive:(WebArchive *)archive
 {
-    WebResource *mainResource = [archive mainResource];
-    if (mainResource) {
-        SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData([mainResource data]), [mainResource MIMEType], [mainResource textEncodingName], KURL());
-        ResourceRequest request([mainResource URL]);
-
-        // hack because Mail checks for this property to detect data / archive loads
-        [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
-
-        RefPtr<DocumentLoader> documentLoader = _private->coreFrame->loader()->client()->createDocumentLoader(request, substituteData);
-
-        [dataSource(documentLoader.get()) _addToUnarchiveState:archive];
-
-        _private->coreFrame->loader()->load(documentLoader.get());
-    }
+    if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
+        _private->coreFrame->loader()->loadArchive(coreArchive);
 }
 
 - (void)stopLoading
index 523aa41..e4ecae1 100644 (file)
@@ -129,8 +129,6 @@ WebView *getWebView(WebFrame *webFrame);
 - (WebFrame *)_findFrameWithSelection;
 - (void)_clearSelectionInOtherFrames;
 
-- (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame;
-
 - (void)_attachScriptDebugger;
 - (void)_detachScriptDebugger;
 
index 1baf4ce..db17f99 100644 (file)
@@ -188,31 +188,6 @@ static NSArray *concatenateArrays(NSArray *first, NSArray *second)
     }
 }
 
-- (void)_loadDataSourceAsWebArchive
-{
-    WebArchive *archive = [[WebArchive alloc] initWithData:[_private->dataSource data]];
-    WebResource *mainResource = [archive mainResource];
-    if (!mainResource) {
-        [archive release];
-        return;
-    }
-    
-    NSData *data = [mainResource data];
-    [data retain];
-    [_private->parsedArchiveData release];
-    _private->parsedArchiveData = data;
-    
-    [_private->dataSource _addToUnarchiveState:archive];
-    [archive release];
-    
-    WebFrame *webFrame = [_private->dataSource webFrame];
-    
-    if (!webFrame)
-        return;
-    
-    core(webFrame)->loader()->continueLoadWithData(SharedBuffer::wrapNSData(data).get(), [mainResource MIMEType], [mainResource textEncodingName], [mainResource URL]);
-}
-
 - (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource
 {
     WebFrame *frame = [dataSource webFrame];
@@ -223,9 +198,7 @@ static NSArray *concatenateArrays(NSArray *first, NSArray *second)
     }
 
     if (frame) {
-        if ([self _isDisplayingWebArchive])
-            [self _loadDataSourceAsWebArchive];
-        else {
+        if (![self _isDisplayingWebArchive]) {
             // Telling the frame we received some data and passing nil as the data is our
             // way to get work done that is normally done when the first bit of data is
             // received, even for the case of a document with no data (like about:blank).
index 874df8b..144323e 100644 (file)
 #import "WebFrameInternal.h"
 #import "WebNSDictionaryExtras.h"
 #import "WebNSURLExtras.h"
+
+#import <WebCore/ArchiveResource.h>
+#import <WebCore/LegacyWebArchive.h>
 #import <WebCore/TextEncoding.h>
+#import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebCoreURLResponse.h>
 
+#import <wtf/PassRefPtr.h>
+
 using namespace WebCore;
 
 static NSString * const WebResourceDataKey =              @"WebResourceData";
@@ -48,29 +54,52 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 @interface WebResourcePrivate : NSObject
 {
 @public
-    NSData *data;
-    NSURL *URL;
-    NSString *frameName;
-    NSString *MIMEType;
-    NSString *textEncodingName;
-    NSURLResponse *response;
-    BOOL shouldIgnoreWhenUnarchiving;
+    ArchiveResource* coreResource;
 }
+
+- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource;
 @end
 
 @implementation WebResourcePrivate
 
+#ifndef BUILDING_ON_TIGER
++ (void)initialize
+{
+    WebCoreObjCFinalizeOnMainThread(self);
+}
+#endif
+
+- (id)init
+{
+    return [super init];
+}
+
+- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)passedResource
+{
+    self = [super init];
+    if (!self)
+        return self;
+    
+    // Acquire the PassRefPtr<>'s ref as our own manual ref
+    coreResource = passedResource.releaseRef();
+
+    return self;
+}
+
 - (void)dealloc
 {
-    [data release];
-    [URL release];
-    [frameName release];
-    [MIMEType release];
-    [textEncodingName release];
-    [response release];
+    if (coreResource)
+        coreResource->deref();
     [super dealloc];
 }
 
+- (void)finalize
+{
+    if (coreResource)
+        coreResource->deref();
+    [super finalize];
+}
+
 @end
 
 @implementation WebResource
@@ -91,45 +120,68 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 
 - (id)initWithCoder:(NSCoder *)decoder
 {
-    self = [self init];
+    self = [super init];
     if (!self)
         return nil;
 
+    NSData *data = nil;
+    NSURL *url = nil;
+    NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
+    NSURLResponse *response = nil;
+    
     @try {
         id object = [decoder decodeObjectForKey:WebResourceDataKey];
         if ([object isKindOfClass:[NSData class]])
-            _private->data = [object retain];
+            data = object;
         object = [decoder decodeObjectForKey:WebResourceURLKey];
         if ([object isKindOfClass:[NSURL class]])
-            _private->URL = [object retain];
+            url = object;
         object = [decoder decodeObjectForKey:WebResourceMIMETypeKey];
         if ([object isKindOfClass:[NSString class]])
-            _private->MIMEType = [object retain];
+            mimeType = object;
         object = [decoder decodeObjectForKey:WebResourceTextEncodingNameKey];
         if ([object isKindOfClass:[NSString class]])
-            _private->textEncodingName = [object retain];
+            textEncoding = object;
         object = [decoder decodeObjectForKey:WebResourceFrameNameKey];
         if ([object isKindOfClass:[NSString class]])
-            _private->frameName = [object retain];
+            frameName = object;
         object = [decoder decodeObjectForKey:WebResourceResponseKey];
         if ([object isKindOfClass:[NSURLResponse class]])
-            _private->response = [object retain];
+            response = object;
     } @catch(id) {
         [self release];
         return nil;
     }
 
+    _private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response)];
+
     return self;
 }
 
 - (void)encodeWithCoder:(NSCoder *)encoder
 {
-    [encoder encodeObject:_private->data forKey:WebResourceDataKey];
-    [encoder encodeObject:_private->URL forKey:WebResourceURLKey];
-    [encoder encodeObject:_private->MIMEType forKey:WebResourceMIMETypeKey];
-    [encoder encodeObject:_private->textEncodingName forKey:WebResourceTextEncodingNameKey];
-    [encoder encodeObject:_private->frameName forKey:WebResourceFrameNameKey];
-    [encoder encodeObject:_private->response forKey:WebResourceResponseKey];
+    ArchiveResource *resource = _private->coreResource;
+    
+    NSData *data = nil;
+    NSURL *url = nil;
+    NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
+    NSURLResponse *response = nil;
+    
+    if (resource) {
+        if (resource->data())
+            data = [resource->data()->createNSData() autorelease];
+        url = resource->url();
+        mimeType = resource->mimeType();
+        textEncoding = resource->textEncoding();
+        frameName = resource->frameName();
+        response = resource->response().nsURLResponse();
+    }
+    [encoder encodeObject:data forKey:WebResourceDataKey];
+    [encoder encodeObject:url forKey:WebResourceURLKey];
+    [encoder encodeObject:mimeType forKey:WebResourceMIMETypeKey];
+    [encoder encodeObject:textEncoding forKey:WebResourceTextEncodingNameKey];
+    [encoder encodeObject:frameName forKey:WebResourceFrameNameKey];
+    [encoder encodeObject:response forKey:WebResourceResponseKey];
 }
 
 - (void)dealloc
@@ -145,27 +197,27 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 
 - (NSData *)data
 {
-    return _private->data;
+    return _private->coreResource ? [_private->coreResource->data()->createNSData() autorelease] : 0;
 }
 
 - (NSURL *)URL
 {
-    return _private->URL;
+    return _private->coreResource ? (NSURL *)_private->coreResource->url() : 0;
 }
 
 - (NSString *)MIMEType
 {
-    return _private->MIMEType;
+    return _private->coreResource ? (NSString *)_private->coreResource->mimeType() : 0;
 }
 
 - (NSString *)textEncodingName
 {
-    return _private->textEncodingName;
+    return _private->coreResource ? (NSString *)_private->coreResource->textEncoding() : 0;
 }
 
 - (NSString *)frameName
 {
-    return _private->frameName;
+    return _private->coreResource ? (NSString *)_private->coreResource->frameName() : 0;
 }
 
 - (id)description
@@ -175,46 +227,34 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 
 @end
 
-@implementation WebResource (WebResourcePrivate)
+@implementation WebResource (WebResourceInternal)
 
-// SPI for Mail (5066325)
-- (void)_ignoreWhenUnarchiving
+- (id)_initWithCoreResource:(WebCore::ArchiveResource *)coreResource
 {
-    _private->shouldIgnoreWhenUnarchiving = YES;
+    self = [super init];
+    if (!self)
+        return nil;
+            
+    _private = [[WebResourcePrivate alloc] initWithCoreResource:coreResource];
+            
+    return self;
 }
 
-- (BOOL)_shouldIgnoreWhenUnarchiving
+- (WebCore::ArchiveResource *)_coreResource
 {
-    return _private->shouldIgnoreWhenUnarchiving;
+    return _private->coreResource;
 }
 
-+ (NSArray *)_resourcesFromPropertyLists:(NSArray *)propertyLists
-{
-    if (![propertyLists isKindOfClass:[NSArray class]]) {
-        return nil;
-    }
-    NSEnumerator *enumerator = [propertyLists objectEnumerator];
-    NSMutableArray *resources = [NSMutableArray array];
-    NSDictionary *propertyList;
-    while ((propertyList = [enumerator nextObject]) != nil) {
-        WebResource *resource = [[WebResource alloc] _initWithPropertyList:propertyList];
-        if (resource) {
-            [resources addObject:resource];
-            [resource release];
-        }
-    }
-    return resources;
-}
+@end
+
+@implementation WebResource (WebResourcePrivate)
 
-+ (NSArray *)_propertyListsFromResources:(NSArray *)resources
+// SPI for Mail (5066325)
+// FIXME: This "ignoreWhenUnarchiving" concept is an ugly one - can we find a cleaner solution for those who need this SPI?
+- (void)_ignoreWhenUnarchiving
 {
-    NSEnumerator *enumerator = [resources objectEnumerator];
-    NSMutableArray *propertyLists = [NSMutableArray array];
-    WebResource *resource;
-    while ((resource = [enumerator nextObject]) != nil) {
-        [propertyLists addObject:[resource _propertyListRepresentation]];
-    }
-    return propertyLists;
+    if (_private->coreResource)
+        _private->coreResource->ignoreWhenUnarchiving();
 }
 
 - (id)_initWithData:(NSData *)data 
@@ -225,30 +265,17 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
            response:(NSURLResponse *)response
            copyData:(BOOL)copyData
 {
-    [self init];    
-    
-    if (!data) {
-        [self release];
-        return nil;
-    }
-    _private->data = copyData ? [data copy] : [data retain];
-    
-    if (!URL) {
-        [self release];
+    self = [super init];
+    if (!self)
         return nil;
-    }
-    _private->URL = [URL copy];
     
-    if (!MIMEType) {
+    if (!data || !URL || !MIMEType) {
         [self release];
         return nil;
     }
-    _private->MIMEType = [MIMEType copy];
-    
-    _private->textEncodingName = [textEncodingName copy];
-    _private->frameName = [frameName copy];
-    _private->response = [response retain];
-        
+            
+    _private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response)];
+            
     return self;
 }
 
@@ -265,90 +292,41 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
                       copyData:NO];    
 }
 
-- (id)_initWithPropertyList:(id)propertyList
+- (NSFileWrapper *)_fileWrapperRepresentation
 {
-    if (![propertyList isKindOfClass:[NSDictionary class]]) {
-        [self release];
-        return nil;
-    }
+    SharedBuffer* coreData = _private->coreResource ? _private->coreResource->data() : 0;
+    NSData *data = coreData ? [coreData->createNSData() autorelease] : nil;
     
-    NSURLResponse *response = nil;
-    NSData *responseData = [propertyList objectForKey:WebResourceResponseKey];
-    if ([responseData isKindOfClass:[NSData class]]) {
-        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData];
-        @try {
-            id responseObject = [unarchiver decodeObjectForKey:WebResourceResponseKey];
-            if ([responseObject isKindOfClass:[NSURLResponse class]])
-                response = responseObject;
-            [unarchiver finishDecoding];
-        } @catch(id) {
-            response = nil;
-        }
-        [unarchiver release];
+    NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
+    NSString *preferredFilename = _private->coreResource ? (NSString *)_private->coreResource->response().suggestedFilename() : nil;
+    if (!preferredFilename || ![preferredFilename length]) {
+        NSURL *url = _private->coreResource ? (NSURL *)_private->coreResource->url() : nil;
+        NSString *mimeType = _private->coreResource ? (NSString *)_private->coreResource->mimeType() : nil;
+        preferredFilename = [url _webkit_suggestedFilenameWithMIMEType:mimeType];
     }
-
-    NSData *data = [propertyList objectForKey:WebResourceDataKey];
-    NSString *URLString = [propertyList _webkit_stringForKey:WebResourceURLKey];
-    return [self _initWithData:[data isKindOfClass:[NSData class]] ? data : nil
-                           URL:URLString ? [NSURL _web_URLWithDataAsString:URLString] : nil
-                      MIMEType:[propertyList _webkit_stringForKey:WebResourceMIMETypeKey]
-              textEncodingName:[propertyList _webkit_stringForKey:WebResourceTextEncodingNameKey]
-                     frameName:[propertyList _webkit_stringForKey:WebResourceFrameNameKey]
-                      response:response
-                      copyData:NO];
-}
-
-- (NSFileWrapper *)_fileWrapperRepresentation
-{
-    NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:_private->data] autorelease];
-    NSString *preferredFilename = [_private->response suggestedFilename];
-    if (!preferredFilename || ![preferredFilename length])
-        preferredFilename = [_private->URL _webkit_suggestedFilenameWithMIMEType:_private->MIMEType];
+    
     [wrapper setPreferredFilename:preferredFilename];
     return wrapper;
 }
 
-- (id)_propertyListRepresentation
-{
-    NSMutableDictionary *propertyList = [NSMutableDictionary dictionary];
-    [propertyList setObject:_private->data forKey:WebResourceDataKey];
-    [propertyList setObject:[_private->URL _web_originalDataAsString] forKey:WebResourceURLKey];
-    [propertyList setObject:_private->MIMEType forKey:WebResourceMIMETypeKey];
-    if (_private->textEncodingName != nil) {
-        [propertyList setObject:_private->textEncodingName forKey:WebResourceTextEncodingNameKey];
-    }
-    if (_private->frameName != nil) {
-        [propertyList setObject:_private->frameName forKey:WebResourceFrameNameKey];
-    }    
-    if (_private->response != nil) {
-        NSMutableData *responseData = [[NSMutableData alloc] init];
-        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:responseData];
-        [archiver encodeObject:_private->response forKey:WebResourceResponseKey];
-        [archiver finishEncoding];
-        [archiver release];
-        [propertyList setObject:responseData forKey:WebResourceResponseKey];
-        [responseData release];
-    }        
-    return propertyList;
-}
-
 - (NSURLResponse *)_response
 {
-    if (_private->response != nil) {
-        return _private->response;
-    }
-    return [[[NSURLResponse alloc] initWithURL:_private->URL
-                                      MIMEType:_private->MIMEType 
-                         expectedContentLength:[_private->data length]
-                              textEncodingName:_private->textEncodingName] autorelease];
+    NSURLResponse *response = nil;
+    if (_private->coreResource)
+        response = _private->coreResource->response().nsURLResponse();
+    
+    return response ? response : [[[NSURLResponse alloc] init] autorelease];        
 }
 
 - (NSString *)_stringValue
 {
-    WebCore::TextEncoding encoding(_private->textEncodingName);
+    WebCore::TextEncoding encoding(_private->coreResource ? (NSString *)_private->coreResource->textEncoding() : nil);
     if (!encoding.isValid())
         encoding = WindowsLatin1Encoding();
-    return encoding.decode(reinterpret_cast<const char*>([_private->data bytes]), [_private->data length]);
+    
+    SharedBuffer* coreData = _private->coreResource ? _private->coreResource->data() : 0;
+    
+    return encoding.decode(reinterpret_cast<const char*>(coreData ? coreData->data() : 0), coreData ? coreData->size() : 0);
 }
 
 @end
diff --git a/WebKit/mac/WebView/WebResourceInternal.h b/WebKit/mac/WebView/WebResourceInternal.h
new file mode 100644 (file)
index 0000000..1e06752
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#import "WebResource.h"
+
+namespace WebCore {
+    class ArchiveResource;
+}
+
+@interface WebResource (WebResourceInternal)
+
+- (id)_initWithCoreResource:(WebCore::ArchiveResource *)coreResource;
+- (WebCore::ArchiveResource *)_coreResource;
+
+@end
index 3a7ee41..80d9835 100644 (file)
 
 - (id)_initWithData:(NSData *)data URL:(NSURL *)URL response:(NSURLResponse *)response;
 
-- (BOOL)_shouldIgnoreWhenUnarchiving;
 - (void)_ignoreWhenUnarchiving;
 
-+ (NSArray *)_resourcesFromPropertyLists:(NSArray *)propertyLists;
-+ (NSArray *)_propertyListsFromResources:(NSArray *)resources;
-
-- (id)_initWithPropertyList:(id)propertyList;
-
 - (NSFileWrapper *)_fileWrapperRepresentation;
-- (id)_propertyListRepresentation;
 - (NSURLResponse *)_response;
 - (NSString *)_stringValue;
 
diff --git a/WebKit/mac/WebView/WebUnarchivingState.m b/WebKit/mac/WebView/WebUnarchivingState.m
deleted file mode 100644 (file)
index c1b975a..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, 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.
- */
-
-#import "WebUnarchivingState.h"
-
-#import "WebArchive.h"
-#import <JavaScriptCore/Assertions.h>
-#import "WebResource.h"
-#import "WebResourcePrivate.h"
-#import "WebNSURLExtras.h"
-
-@implementation WebUnarchivingState
-
-- (id)init
-{
-    if (!(self = [super init]))
-        return nil;
-    
-    archivedSubframes = [[NSMutableDictionary alloc] init];
-    archivedResources = [[NSMutableDictionary alloc] init];
-
-    return self;
-}
-
-- (void)dealloc
-{
-    [archivedSubframes release];
-    [archivedResources release];
-    [super dealloc];
-}
-
-- (void)addArchive:(WebArchive *)archive
-{
-    NSEnumerator *enumerator = [[archive subresources] objectEnumerator];
-    WebResource *subresource;
-    while ((subresource = [enumerator nextObject]) != nil)
-        [archivedResources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
-
-    enumerator = [[archive subframeArchives] objectEnumerator];
-    WebArchive *subframeArchive;
-    while ((subframeArchive = [enumerator nextObject]) != nil) {
-        NSString *frameName = [[subframeArchive mainResource] frameName];
-        if (frameName)
-            [archivedSubframes setObject:subframeArchive forKey:frameName];
-    }
-}
-
-- (void)addResource:(WebResource *)subresource
-{
-    [archivedResources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
-}
-
-- (WebResource *)archivedResourceForURL:(NSURL *)URL
-{
-    WebResource *resource = [archivedResources objectForKey:[URL _web_originalDataAsString]];
-    if ([resource _shouldIgnoreWhenUnarchiving]) 
-        return nil;
-    return resource;
-}
-
-- (WebArchive *)popSubframeArchiveWithFrameName:(NSString *)frameName
-{
-    ASSERT(frameName != nil);
-    
-    WebArchive *archive = [[[archivedSubframes objectForKey:frameName] retain] autorelease];
-    if (archive != nil)
-        [archivedSubframes removeObjectForKey:frameName];
-
-    return archive;
-}
-
-@end