RetainPtr<CFDictionaryRef> LegacyWebArchive::createPropertyListRepresentation(Archive* archive) { RetainPtr<CFMutableDictionaryRef> propertyList = adoptCF(CFDictionaryCreateMutable(0, 3, 0, &kCFTypeDictionaryValueCallBacks)); RetainPtr<CFDictionaryRef> mainResourceDict = createPropertyListRepresentation(archive->mainResource(), MainResource); ASSERT(mainResourceDict); if (!mainResourceDict) return nullptr; CFDictionarySetValue(propertyList.get(), LegacyWebArchiveMainResourceKey, mainResourceDict.get()); RetainPtr<CFMutableArrayRef> subresourcesArray = adoptCF(CFArrayCreateMutable(0, archive->subresources().size(), &kCFTypeArrayCallBacks)); for (auto& resource : archive->subresources()) { if (RetainPtr<CFDictionaryRef> subresource = createPropertyListRepresentation(resource.get(), 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)); for (auto& subframe : archive->subframeArchives()) { if (RetainPtr<CFDictionaryRef> subframeArchive = createPropertyListRepresentation(subframe.get())) 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; }
RetainPtr<CFDataRef> LegacyWebArchive::rawDataRepresentation() { RetainPtr<CFDictionaryRef> propertyList = createPropertyListRepresentation(this); ASSERT(propertyList); if (!propertyList) { LOG(Archives, "LegacyWebArchive - Failed to create property list for archive, returning no data"); return 0; } RetainPtr<CFWriteStreamRef> stream(AdoptCF, CFWriteStreamCreateWithAllocatedBuffers(0, 0)); CFWriteStreamOpen(stream.get()); CFPropertyListWriteToStream(propertyList.get(), stream.get(), kCFPropertyListBinaryFormat_v1_0, 0); RetainPtr<CFDataRef> plistData(AdoptCF, static_cast<CFDataRef>(CFWriteStreamCopyProperty(stream.get(), kCFStreamPropertyDataWritten))); ASSERT(plistData); CFWriteStreamClose(stream.get()); if (!plistData) { LOG(Archives, "LegacyWebArchive - Failed to convert property list into raw data, returning no data"); return 0; } return plistData; }
RetainPtr<CFDictionaryRef> LegacyWebArchive::createPropertyListRepresentation(ArchiveResource* resource, MainResourceStatus isMainResource) { if (!resource) { // The property list representation of a null/empty WebResource has the following 3 objects stored as nil. // FIXME: 0 is not serializable. Presumably we need to use kCFNull here instead for compatibility. // FIXME: But why do we need to support a resource of 0? Who relies on that? RetainPtr<CFMutableDictionaryRef> propertyList = adoptCF(CFDictionaryCreateMutable(0, 3, 0, 0)); CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, 0); CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, 0); CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, 0); return propertyList; } RetainPtr<CFMutableDictionaryRef> propertyList = adoptCF(CFDictionaryCreateMutable(0, 6, 0, &kCFTypeDictionaryValueCallBacks)); // Resource data can be empty, but must be represented by an empty CFDataRef SharedBuffer* data = resource->data(); RetainPtr<CFDataRef> cfData; if (data) cfData = data->createCFData(); else cfData = adoptCF(CFDataCreate(0, 0, 0)); CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceDataKey, cfData.get()); // Resource URL cannot be null if (RetainPtr<CFStringRef> cfURL = resource->url().string().createCFString()) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceURLKey, cfURL.get()); else { LOG(Archives, "LegacyWebArchive - NULL resource URL is invalid - returning null property list"); return 0; } // FrameName should be left out if empty for subresources, but always included for main resources const String& frameName(resource->frameName()); if (!frameName.isEmpty() || isMainResource) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceFrameNameKey, frameName.createCFString().get()); // Set MIMEType, TextEncodingName, and ResourceResponse only if they actually exist const String& mimeType(resource->mimeType()); if (!mimeType.isEmpty()) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceMIMETypeKey, mimeType.createCFString().get()); const String& textEncoding(resource->textEncoding()); if (!textEncoding.isEmpty()) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceTextEncodingNameKey, textEncoding.createCFString().get()); // Don't include the resource response for the main resource if (!isMainResource) { RetainPtr<CFDataRef> resourceResponseData = createPropertyListRepresentation(resource->response()); if (resourceResponseData) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveResourceResponseKey, resourceResponseData.get()); } return propertyList; }
RetainPtr<CFDictionaryRef> LegacyWebArchive::createPropertyListRepresentation(Archive* archive) { RetainPtr<CFMutableDictionaryRef> propertyList(AdoptCF, CFDictionaryCreateMutable(0, 3, 0, &kCFTypeDictionaryValueCallBacks)); RetainPtr<CFDictionaryRef> mainResourceDict = createPropertyListRepresentation(archive->mainResource(), MainResource); ASSERT(mainResourceDict); if (!mainResourceDict) return 0; CFDictionarySetValue(propertyList.get(), LegacyWebArchiveMainResourceKey, mainResourceDict.get()); RetainPtr<CFMutableArrayRef> subresourcesArray(AdoptCF, CFArrayCreateMutable(0, archive->subresources().size(), &kCFTypeArrayCallBacks)); const Vector<RefPtr<ArchiveResource> >& subresources(archive->subresources()); for (unsigned i = 0; i < subresources.size(); ++i) { RetainPtr<CFDictionaryRef> subresource = createPropertyListRepresentation(subresources[i].get(), Subresource); if (subresource) CFArrayAppendValue(subresourcesArray.get(), subresource.get()); else LOG(Archives, "LegacyWebArchive - Failed to create property list for subresource"); } if (CFArrayGetCount(subresourcesArray.get())) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubresourcesKey, subresourcesArray.get()); RetainPtr<CFMutableArrayRef> subframesArray(AdoptCF, CFArrayCreateMutable(0, archive->subframeArchives().size(), &kCFTypeArrayCallBacks)); const Vector<RefPtr<Archive> >& subframeArchives(archive->subframeArchives()); for (unsigned i = 0; i < subframeArchives.size(); ++i) { RetainPtr<CFDictionaryRef> subframeArchive = createPropertyListRepresentation(subframeArchives[i].get()); if (subframeArchive) CFArrayAppendValue(subframesArray.get(), subframeArchive.get()); else LOG(Archives, "LegacyWebArchive - Failed to create property list for subframe archive"); } if (CFArrayGetCount(subframesArray.get())) CFDictionarySetValue(propertyList.get(), LegacyWebArchiveSubframeArchivesKey, subframesArray.get()); return propertyList; }