WebKitTestRunner needs testRunner.dumpDOMAsWebArchive

https://bugs.webkit.org/show_bug.cgi?id=42324
<rdar://problem/8193633>

Patch by Alex Christensen <achristensen@apple.com> on 2013-05-07
Reviewed by Tim Horton.

* Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
Added dumpDOMAsWebArchive JavaScript function to be called by test cases.
* Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::dumpDOMAsWebArchive):
Added dumpDOMAsWebArchive code that is called when dumping.
(WTR::InjectedBundlePage::dump):
Made DOMAsWebArchive case when dumping call dumpDOMAsWebArchive.
* Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h:
(InjectedBundlePage):
Added dumpDOMAsWebArchive declaration.
* Tools/WebKitTestRunner/InjectedBundle/TestRunner.h:
(WTR::TestRunner::dumpDOMAsWebArchive):
Added dumpDOMAsWebArchive JS callback function that sets m_whatToDump to DOMAsWebArchive.
* Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
Added WebArchiveDumpSupport.cpp, WebArchiveDumpSupport.h, WebArchiveDumpSupportMac.mm to project.
* Tools/WebKitTestRunner/cf: Added.
* Tools/WebKitTestRunner/cf/WebArchiveDumpSupport.cpp: Added.
Copied from Tools/DumpRenderTree/cf for createXMLStringFromWebArchiveData and other functions it uses.
(convertMIMEType):
(convertWebResourceDataToString):
(normalizeHTTPResponseHeaderFields):
(normalizeWebResourceURL):
(convertWebResourceResponseToDictionary):
(compareResourceURLs):
(createXMLStringFromWebArchiveData):
* Tools/WebKitTestRunner/cf/WebArchiveDumpSupport.h: Added.
Copied from Tools/DumpRenderTree/cf for used symbol declarations.
* Tools/WebKitTestRunner/mac/WebArchiveDumpSupportMac.mm: Added.
Copied from Tools/DumpRenderTree/mac for used functions.
(createCFURLResponseFromResponseData):
(supportedNonImageMIMETypes):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@149692 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent cfe8a86d
2013-05-07 Alex Christensen <achristensen@apple.com>
WebKitTestRunner needs testRunner.dumpDOMAsWebArchive
https://bugs.webkit.org/show_bug.cgi?id=42324
<rdar://problem/8193633>
Reviewed by Tim Horton.
* Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
Added dumpDOMAsWebArchive JavaScript function to be called by test cases.
* Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::dumpDOMAsWebArchive):
Added dumpDOMAsWebArchive code that is called when dumping.
(WTR::InjectedBundlePage::dump):
Made DOMAsWebArchive case when dumping call dumpDOMAsWebArchive.
* Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h:
(InjectedBundlePage):
Added dumpDOMAsWebArchive declaration.
* Tools/WebKitTestRunner/InjectedBundle/TestRunner.h:
(WTR::TestRunner::dumpDOMAsWebArchive):
Added dumpDOMAsWebArchive JS callback function that sets m_whatToDump to DOMAsWebArchive.
* Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
Added WebArchiveDumpSupport.cpp, WebArchiveDumpSupport.h, WebArchiveDumpSupportMac.mm to project.
* Tools/WebKitTestRunner/cf: Added.
* Tools/WebKitTestRunner/cf/WebArchiveDumpSupport.cpp: Added.
Copied from Tools/DumpRenderTree/cf for createXMLStringFromWebArchiveData and other functions it uses.
(convertMIMEType):
(convertWebResourceDataToString):
(normalizeHTTPResponseHeaderFields):
(normalizeWebResourceURL):
(convertWebResourceResponseToDictionary):
(compareResourceURLs):
(createXMLStringFromWebArchiveData):
* Tools/WebKitTestRunner/cf/WebArchiveDumpSupport.h: Added.
Copied from Tools/DumpRenderTree/cf for used symbol declarations.
* Tools/WebKitTestRunner/mac/WebArchiveDumpSupportMac.mm: Added.
Copied from Tools/DumpRenderTree/mac for used functions.
(createCFURLResponseFromResponseData):
(supportedNonImageMIMETypes):
2013-05-07 Alex Christensen <achristensen@apple.com>
Updated style of WebArchiveDumpSupport before putting it into WebKitTestRunner.
......
......@@ -47,6 +47,7 @@ interface TestRunner {
void dumpWillCacheResponse();
void dumpApplicationCacheDelegateCallbacks();
void dumpDatabaseCallbacks();
void dumpDOMAsWebArchive();
// Special options.
void keepWebHistory();
......
......@@ -48,6 +48,10 @@
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#if USE(CF)
#include "WebArchiveDumpSupport.h"
#endif
#if PLATFORM(QT)
#include "DumpRenderTreeSupportQt.h"
#endif
......@@ -837,6 +841,17 @@ void InjectedBundlePage::dumpAllFramesText(StringBuilder& stringBuilder)
dumpDescendantFramesText(frame, stringBuilder);
}
void InjectedBundlePage::dumpDOMAsWebArchive(WKBundleFrameRef frame, StringBuilder& stringBuilder)
{
#if USE(CF)
WKDataRef wkData = WKBundleFrameCopyWebArchive(frame);
RetainPtr<CFDataRef> cfData = adoptCF(CFDataCreate(0, WKDataGetBytes(wkData), WKDataGetSize(wkData)));
RetainPtr<CFStringRef> cfString = adoptCF(createXMLStringFromWebArchiveData(cfData.get()));
stringBuilder.append(cfString.get());
#endif
}
void InjectedBundlePage::dump()
{
ASSERT(InjectedBundle::shared().isTestRunning());
......@@ -868,6 +883,9 @@ void InjectedBundlePage::dump()
break;
case TestRunner::Audio:
break;
case TestRunner::DOMAsWebArchive:
dumpDOMAsWebArchive(frame, stringBuilder);
break;
}
if (InjectedBundle::shared().testRunner()->shouldDumpAllFrameScrollPositions())
......
......@@ -166,6 +166,7 @@ private:
void dumpAllFramesText(WTF::StringBuilder&);
void dumpAllFrameScrollPositions(WTF::StringBuilder&);
void dumpDOMAsWebArchive(WKBundleFrameRef, WTF::StringBuilder&);
void platformDidStartProvisionalLoadForFrame(WKBundleFrameRef);
......
......@@ -88,6 +88,7 @@ public:
void dumpWillCacheResponse() { m_dumpWillCacheResponse = true; }
void dumpApplicationCacheDelegateCallbacks() { m_dumpApplicationCacheDelegateCallbacks = true; }
void dumpDatabaseCallbacks() { m_dumpDatabaseCallbacks = true; }
void dumpDOMAsWebArchive() { m_whatToDump = DOMAsWebArchive; }
void setShouldDumpFrameLoadCallbacks(bool value) { m_dumpFrameLoadCallbacks = value; }
void setShouldDumpProgressFinishedCallback(bool value) { m_dumpProgressFinishedCallback = value; }
......@@ -163,7 +164,7 @@ public:
// Audio testing.
void setAudioResult(JSContextRef, JSValueRef data);
enum WhatToDump { RenderTree, MainFrameText, AllFramesText, Audio };
enum WhatToDump { RenderTree, MainFrameText, AllFramesText, Audio, DOMAsWebArchive };
WhatToDump whatToDump() const { return m_whatToDump; }
bool shouldDumpAllFrameScrollPositions() const { return m_shouldDumpAllFrameScrollPositions; }
......
......@@ -44,6 +44,8 @@
5641E2D014335E95008307E5 /* JSTextInputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5641E2CE14335E95008307E5 /* JSTextInputController.cpp */; };
5664A49A14326384008881BE /* TextInputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5664A49814326384008881BE /* TextInputController.cpp */; };
5670B8281386FCA5002EB355 /* EventSenderProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5670B8271386FCA5002EB355 /* EventSenderProxy.mm */; };
5C45C30F17398E290079714E /* WebArchiveDumpSupportMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C45C30E17398E290079714E /* WebArchiveDumpSupportMac.mm */; };
5C45C31317398E480079714E /* WebArchiveDumpSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C45C31117398E480079714E /* WebArchiveDumpSupport.cpp */; };
6510A78211EC643800410867 /* AHEM____.TTF in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77711EC643800410867 /* AHEM____.TTF */; };
6510A78411EC643800410867 /* WebKitWeightWatcher100.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77911EC643800410867 /* WebKitWeightWatcher100.ttf */; };
6510A78511EC643800410867 /* WebKitWeightWatcher200.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77A11EC643800410867 /* WebKitWeightWatcher200.ttf */; };
......@@ -149,6 +151,9 @@
5670B8271386FCA5002EB355 /* EventSenderProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EventSenderProxy.mm; sourceTree = "<group>"; };
583913D014335E95008307E5 /* JSAccessibilityController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSAccessibilityController.cpp; path = DerivedSources/WebKitTestRunner/JSAccessibilityController.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
583913D114335E95008307E5 /* JSAccessibilityController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSAccessibilityController.h; path = DerivedSources/WebKitTestRunner/JSAccessibilityController.h; sourceTree = BUILT_PRODUCTS_DIR; };
5C45C30E17398E290079714E /* WebArchiveDumpSupportMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebArchiveDumpSupportMac.mm; path = mac/WebArchiveDumpSupportMac.mm; sourceTree = SOURCE_ROOT; };
5C45C31117398E480079714E /* WebArchiveDumpSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebArchiveDumpSupport.cpp; path = cf/WebArchiveDumpSupport.cpp; sourceTree = SOURCE_ROOT; };
5C45C31217398E480079714E /* WebArchiveDumpSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebArchiveDumpSupport.h; path = cf/WebArchiveDumpSupport.h; sourceTree = SOURCE_ROOT; };
6510A77711EC643800410867 /* AHEM____.TTF */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AHEM____.TTF"; path = "fonts/AHEM____.TTF"; sourceTree = "<group>"; };
6510A77911EC643800410867 /* WebKitWeightWatcher100.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher100.ttf; path = fonts/WebKitWeightWatcher100.ttf; sourceTree = "<group>"; };
6510A77A11EC643800410867 /* WebKitWeightWatcher200.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = WebKitWeightWatcher200.ttf; path = fonts/WebKitWeightWatcher200.ttf; sourceTree = "<group>"; };
......@@ -327,9 +332,19 @@
name = Accessibility;
sourceTree = "<group>";
};
5C45C31017398E370079714E /* cf */ = {
isa = PBXGroup;
children = (
5C45C31117398E480079714E /* WebArchiveDumpSupport.cpp */,
5C45C31217398E480079714E /* WebArchiveDumpSupport.h */,
);
name = cf;
sourceTree = "<group>";
};
65EB859E11EC67CC0034D300 /* mac */ = {
isa = PBXGroup;
children = (
5C45C30E17398E290079714E /* WebArchiveDumpSupportMac.mm */,
65EB859F11EC67CC0034D300 /* ActivateFonts.mm */,
BC8DAD771316D7B900EC96FC /* InjectedBundleMac.mm */,
0FAF67EE160D6C100077CB2B /* InjectedBundlePageMac.mm */,
......@@ -357,6 +372,7 @@
BC25183511D1571D002EBC01 /* InjectedBundle */ = {
isa = PBXGroup;
children = (
5C45C31017398E370079714E /* cf */,
BC952C0A11F3B939003398B4 /* Bindings */,
BC14E4E0120E02F900826C0C /* Controllers */,
BC952D3A11F3BF1F003398B4 /* Derived Sources */,
......@@ -515,6 +531,8 @@
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "WebKitTestRunner" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
......@@ -626,6 +644,8 @@
5641E2D014335E95008307E5 /* JSTextInputController.cpp in Sources */,
BC952C0D11F3B965003398B4 /* JSWrapper.cpp in Sources */,
BCC9981811D3F51E0017BCA2 /* TestRunner.cpp in Sources */,
5C45C30F17398E290079714E /* WebArchiveDumpSupportMac.mm in Sources */,
5C45C31317398E480079714E /* WebArchiveDumpSupport.cpp in Sources */,
C0CE720B1247C93300BC0EC4 /* TestRunnerMac.mm in Sources */,
5664A49A14326384008881BE /* TextInputController.cpp in Sources */,
);
......
/*
* Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "WebArchiveDumpSupport.h"
#include <CFNetwork/CFNetwork.h>
#include <CoreFoundation/CoreFoundation.h>
#include <wtf/RetainPtr.h>
extern "C" {
CFURLRef CFURLResponseGetURL(CFURLResponseRef);
CFStringRef CFURLResponseGetMIMEType(CFURLResponseRef);
CFStringRef CFURLResponseGetTextEncodingName(CFURLResponseRef);
SInt64 CFURLResponseGetExpectedContentLength(CFURLResponseRef);
CFHTTPMessageRef CFURLResponseGetHTTPResponse(CFURLResponseRef);
CFTypeID CFURLResponseGetTypeID(void);
}
static void convertMIMEType(CFMutableStringRef mimeType)
{
#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1050
// Workaround for <rdar://problem/5539824> on Leopard
if (CFStringCompare(mimeType, CFSTR("text/xml"), kCFCompareAnchored | kCFCompareCaseInsensitive) == kCFCompareEqualTo)
CFStringReplaceAll(mimeType, CFSTR("application/xml"));
#endif
// Workaround for <rdar://problem/6234318> with Dashcode 2.0
if (CFStringCompare(mimeType, CFSTR("application/x-javascript"), kCFCompareAnchored | kCFCompareCaseInsensitive) == kCFCompareEqualTo)
CFStringReplaceAll(mimeType, CFSTR("text/javascript"));
}
static void convertWebResourceDataToString(CFMutableDictionaryRef resource)
{
CFMutableStringRef mimeType = (CFMutableStringRef)CFDictionaryGetValue(resource, CFSTR("WebResourceMIMEType"));
CFStringLowercase(mimeType, CFLocaleGetSystem());
convertMIMEType(mimeType);
CFArrayRef supportedMIMETypes = supportedNonImageMIMETypes();
if (CFStringHasPrefix(mimeType, CFSTR("text/")) || CFArrayContainsValue(supportedMIMETypes, CFRangeMake(0, CFArrayGetCount(supportedMIMETypes)), mimeType)) {
CFStringRef textEncodingName = static_cast<CFStringRef>(CFDictionaryGetValue(resource, CFSTR("WebResourceTextEncodingName")));
CFStringEncoding stringEncoding;
if (textEncodingName && CFStringGetLength(textEncodingName))
stringEncoding = CFStringConvertIANACharSetNameToEncoding(textEncodingName);
else
stringEncoding = kCFStringEncodingUTF8;
CFDataRef data = static_cast<CFDataRef>(CFDictionaryGetValue(resource, CFSTR("WebResourceData")));
RetainPtr<CFStringRef> dataAsString(AdoptCF, CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, stringEncoding));
if (dataAsString)
CFDictionarySetValue(resource, CFSTR("WebResourceData"), dataAsString.get());
}
}
static void normalizeHTTPResponseHeaderFields(CFMutableDictionaryRef fields)
{
// Normalize headers
if (CFDictionaryContainsKey(fields, CFSTR("Date")))
CFDictionarySetValue(fields, CFSTR("Date"), CFSTR("Sun, 16 Nov 2008 17:00:00 GMT"));
if (CFDictionaryContainsKey(fields, CFSTR("Last-Modified")))
CFDictionarySetValue(fields, CFSTR("Last-Modified"), CFSTR("Sun, 16 Nov 2008 16:55:00 GMT"));
if (CFDictionaryContainsKey(fields, CFSTR("Etag")))
CFDictionarySetValue(fields, CFSTR("Etag"), CFSTR("\"301925-21-45c7d72d3e780\""));
if (CFDictionaryContainsKey(fields, CFSTR("Server")))
CFDictionarySetValue(fields, CFSTR("Server"), CFSTR("Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l PHP/5.2.6"));
// Remove headers
CFDictionaryRemoveValue(fields, CFSTR("Connection"));
CFDictionaryRemoveValue(fields, CFSTR("Keep-Alive"));
}
static void normalizeWebResourceURL(CFMutableStringRef webResourceURL)
{
static CFIndex fileUrlLength = CFStringGetLength(CFSTR("file://"));
CFRange layoutTestsWebArchivePathRange = CFStringFind(webResourceURL, CFSTR("/LayoutTests/"), kCFCompareBackwards);
if (layoutTestsWebArchivePathRange.location == kCFNotFound)
return;
CFRange currentWorkingDirectoryRange = CFRangeMake(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength);
CFStringReplace(webResourceURL, currentWorkingDirectoryRange, CFSTR(""));
}
static void convertWebResourceResponseToDictionary(CFMutableDictionaryRef propertyList)
{
CFDataRef responseData = static_cast<CFDataRef>(CFDictionaryGetValue(propertyList, CFSTR("WebResourceResponse"))); // WebResourceResponseKey in WebResource.m
if (CFGetTypeID(responseData) != CFDataGetTypeID())
return;
RetainPtr<CFURLResponseRef> response(AdoptCF, createCFURLResponseFromResponseData(responseData));
if (!response)
return;
RetainPtr<CFMutableDictionaryRef> responseDictionary(AdoptCF, CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
RetainPtr<CFMutableStringRef> urlString(AdoptCF, CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFURLGetString(CFURLResponseGetURL(response.get()))));
normalizeWebResourceURL(urlString.get());
CFDictionarySetValue(responseDictionary.get(), CFSTR("URL"), urlString.get());
RetainPtr<CFMutableStringRef> mimeTypeString(AdoptCF, CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFURLResponseGetMIMEType(response.get())));
convertMIMEType(mimeTypeString.get());
CFDictionarySetValue(responseDictionary.get(), CFSTR("MIMEType"), mimeTypeString.get());
CFStringRef textEncodingName = CFURLResponseGetTextEncodingName(response.get());
if (textEncodingName)
CFDictionarySetValue(responseDictionary.get(), CFSTR("textEncodingName"), textEncodingName);
SInt64 expectedContentLength = CFURLResponseGetExpectedContentLength(response.get());
RetainPtr<CFNumberRef> expectedContentLengthNumber(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &expectedContentLength));
CFDictionarySetValue(responseDictionary.get(), CFSTR("expectedContentLength"), expectedContentLengthNumber.get());
if (CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(response.get())) {
RetainPtr<CFDictionaryRef> allHeaders(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpMessage));
RetainPtr<CFMutableDictionaryRef> allHeaderFields(AdoptCF, CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, allHeaders.get()));
normalizeHTTPResponseHeaderFields(allHeaderFields.get());
CFDictionarySetValue(responseDictionary.get(), CFSTR("allHeaderFields"), allHeaderFields.get());
CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(httpMessage);
RetainPtr<CFNumberRef> statusCodeNumber(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &statusCode));
CFDictionarySetValue(responseDictionary.get(), CFSTR("statusCode"), statusCodeNumber.get());
}
CFDictionarySetValue(propertyList, CFSTR("WebResourceResponse"), responseDictionary.get());
}
static CFComparisonResult compareResourceURLs(const void *val1, const void *val2, void *context)
{
CFStringRef url1 = static_cast<CFStringRef>(CFDictionaryGetValue(static_cast<CFDictionaryRef>(val1), CFSTR("WebResourceURL")));
CFStringRef url2 = static_cast<CFStringRef>(CFDictionaryGetValue(static_cast<CFDictionaryRef>(val2), CFSTR("WebResourceURL")));
return CFStringCompare(url1, url2, kCFCompareAnchored);
}
CFStringRef createXMLStringFromWebArchiveData(CFDataRef webArchiveData)
{
CFErrorRef error = 0;
CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0;
#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1050
CFIndex bytesCount = CFDataGetLength(webArchiveData);
RetainPtr<CFReadStreamRef> readStream(AdoptCF, CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, CFDataGetBytePtr(webArchiveData), bytesCount, kCFAllocatorNull));
CFReadStreamOpen(readStream.get());
RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, (CFMutableDictionaryRef)CFPropertyListCreateFromStream(kCFAllocatorDefault, readStream.get(), bytesCount, kCFPropertyListMutableContainersAndLeaves, &format, 0));
CFReadStreamClose(readStream.get());
#else
RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, (CFMutableDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, webArchiveData, kCFPropertyListMutableContainersAndLeaves, &format, &error));
#endif
if (!propertyList) {
if (error)
return CFErrorCopyDescription(error);
return static_cast<CFStringRef>(CFRetain(CFSTR("An unknown error occurred converting data to property list.")));
}
RetainPtr<CFMutableArrayRef> resources(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
CFArrayAppendValue(resources.get(), propertyList.get());
while (CFArrayGetCount(resources.get())) {
RetainPtr<CFMutableDictionaryRef> resourcePropertyList = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(resources.get(), 0);
CFArrayRemoveValueAtIndex(resources.get(), 0);
CFMutableDictionaryRef mainResource = (CFMutableDictionaryRef)CFDictionaryGetValue(resourcePropertyList.get(), CFSTR("WebMainResource"));
normalizeWebResourceURL((CFMutableStringRef)CFDictionaryGetValue(mainResource, CFSTR("WebResourceURL")));
convertWebResourceDataToString(mainResource);
// Add subframeArchives to list for processing
CFMutableArrayRef subframeArchives = (CFMutableArrayRef)CFDictionaryGetValue(resourcePropertyList.get(), CFSTR("WebSubframeArchives")); // WebSubframeArchivesKey in WebArchive.m
if (subframeArchives)
CFArrayAppendArray(resources.get(), subframeArchives, CFRangeMake(0, CFArrayGetCount(subframeArchives)));
CFMutableArrayRef subresources = (CFMutableArrayRef)CFDictionaryGetValue(resourcePropertyList.get(), CFSTR("WebSubresources")); // WebSubresourcesKey in WebArchive.m
if (!subresources)
continue;
CFIndex subresourcesCount = CFArrayGetCount(subresources);
for (CFIndex i = 0; i < subresourcesCount; ++i) {
CFMutableDictionaryRef subresourcePropertyList = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(subresources, i);
normalizeWebResourceURL((CFMutableStringRef)CFDictionaryGetValue(subresourcePropertyList, CFSTR("WebResourceURL")));
convertWebResourceResponseToDictionary(subresourcePropertyList);
convertWebResourceDataToString(subresourcePropertyList);
}
// Sort the subresources so they're always in a predictable order for the dump
CFArraySortValues(subresources, CFRangeMake(0, CFArrayGetCount(subresources)), compareResourceURLs, 0);
}
error = 0;
#if __MAC_OS_X_VERSION_MIN_REQUIRED == 1050
RetainPtr<CFDataRef> xmlData(AdoptCF, CFPropertyListCreateXMLData(kCFAllocatorDefault, propertyList.get()));
#else
RetainPtr<CFDataRef> xmlData(AdoptCF, CFPropertyListCreateData(kCFAllocatorDefault, propertyList.get(), kCFPropertyListXMLFormat_v1_0, 0, &error));
#endif
if (!xmlData) {
if (error)
return CFErrorCopyDescription(error);
return static_cast<CFStringRef>(CFRetain(CFSTR("An unknown error occurred converting property list to data.")));
}
RetainPtr<CFStringRef> xmlString(AdoptCF, CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, xmlData.get(), kCFStringEncodingUTF8));
RetainPtr<CFMutableStringRef> string(AdoptCF, CFStringCreateMutableCopy(kCFAllocatorDefault, 0, xmlString.get()));
// Replace "Apple Computer" with "Apple" in the DTD declaration.
CFStringFindAndReplace(string.get(), CFSTR("-//Apple Computer//"), CFSTR("-//Apple//"), CFRangeMake(0, CFStringGetLength(string.get())), 0);
return string.leakRef();
}
/*
* Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WebArchiveDumpSupport_h
#define WebArchiveDumpSupport_h
#include <CoreFoundation/CoreFoundation.h>
typedef struct _CFURLResponse* CFURLResponseRef;
CFStringRef createXMLStringFromWebArchiveData(CFDataRef webArchiveData);
// MARK: -
// MARK: Platform-specific methods
CFURLResponseRef createCFURLResponseFromResponseData(CFDataRef responseData);
CFArrayRef supportedNonImageMIMETypes();
#endif /* WebArchiveDumpSupport_h */
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "WebArchiveDumpSupport.h"
#import <CFNetwork/CFHTTPMessage.h>
#import <Foundation/Foundation.h>
#import <WebKit/WebHTMLRepresentation.h>
#import <wtf/RetainPtr.h>
extern "C" {
enum CFURLCacheStoragePolicy {
kCFURLCacheStorageAllowed = 0,
kCFURLCacheStorageAllowedInMemoryOnly = 1,
kCFURLCacheStorageNotAllowed = 2
};
typedef enum CFURLCacheStoragePolicy CFURLCacheStoragePolicy;
extern const CFStringRef kCFHTTPVersion1_1;
CFURLResponseRef CFURLResponseCreate(CFAllocatorRef alloc, CFURLRef URL, CFStringRef mimeType, SInt64 expectedContentLength, CFStringRef textEncodingName, CFURLCacheStoragePolicy recommendedPolicy);
CFURLResponseRef CFURLResponseCreateWithHTTPResponse(CFAllocatorRef alloc, CFURLRef URL, CFHTTPMessageRef httpResponse, CFURLCacheStoragePolicy recommendedPolicy);
void CFURLResponseSetExpectedContentLength(CFURLResponseRef response, SInt64 length);
void CFURLResponseSetMIMEType(CFURLResponseRef response, CFStringRef mimeType);
}
CFURLResponseRef createCFURLResponseFromResponseData(CFDataRef responseData)
{
// Decode NSURLResponse
RetainPtr<NSKeyedUnarchiver> unarchiver(AdoptNS, [[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)responseData]);
NSURLResponse *response = [unarchiver.get() decodeObjectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m
[unarchiver.get() finishDecoding];
if (![response isKindOfClass:[NSHTTPURLResponse class]])
return CFURLResponseCreate(kCFAllocatorDefault, (CFURLRef)[response URL], (CFStringRef)[response MIMEType], [response expectedContentLength], (CFStringRef)[response textEncodingName], kCFURLCacheStorageAllowed);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
// NSURLResponse is not toll-free bridged to CFURLResponse.
RetainPtr<CFHTTPMessageRef> httpMessage(AdoptCF, CFHTTPMessageCreateResponse(kCFAllocatorDefault, [httpResponse statusCode], 0, kCFHTTPVersion1_1));
NSDictionary *headerFields = [httpResponse allHeaderFields];
for (NSString *headerField in [headerFields keyEnumerator])
CFHTTPMessageSetHeaderFieldValue(httpMessage.get(), (CFStringRef)headerField, (CFStringRef)[headerFields objectForKey:headerField]);
return CFURLResponseCreateWithHTTPResponse(kCFAllocatorDefault, (CFURLRef)[response URL], httpMessage.get(), kCFURLCacheStorageAllowed);
}
CFArrayRef supportedNonImageMIMETypes()
{
return (CFArrayRef)[WebHTMLRepresentation supportedNonImageMIMETypes];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment