RefPtr<LegacyWebArchive> LegacyWebArchive::create(const URL&, SharedBuffer& data) { LOG(Archives, "LegacyWebArchive - Creating from raw data"); Ref<LegacyWebArchive> archive = create(); RetainPtr<CFDataRef> cfData = data.createCFData(); if (!cfData) return nullptr; CFErrorRef error = nullptr; RetainPtr<CFDictionaryRef> plist = adoptCF(static_cast<CFDictionaryRef>(CFPropertyListCreateWithData(0, cfData.get(), kCFPropertyListImmutable, 0, &error))); if (!plist) { #ifndef NDEBUG RetainPtr<CFStringRef> errorString = error ? adoptCF(CFErrorCopyDescription(error)) : 0; const char* cError = errorString ? CFStringGetCStringPtr(errorString.get(), kCFStringEncodingUTF8) : "unknown error"; LOG(Archives, "LegacyWebArchive - Error parsing PropertyList from archive data - %s", cError); #endif if (error) CFRelease(error); return nullptr; } if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) { LOG(Archives, "LegacyWebArchive - Archive property list is not the expected CFDictionary, aborting invalid WebArchive"); return nullptr; } if (!archive->extract(plist.get())) return nullptr; return WTFMove(archive); }
std::unique_ptr<FontCustomPlatformData> createFontCustomPlatformData(SharedBuffer& buffer) { RetainPtr<CFDataRef> bufferData = buffer.createCFData(); RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontManagerCreateFontDescriptorFromData(bufferData.get())); if (!fontDescriptor) return nullptr; return std::make_unique<FontCustomPlatformData>(fontDescriptor.get()); }
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; }
void ImageDecoder::setData(SharedBuffer& data, bool allDataReceived) { m_isAllDataReceived = allDataReceived; #if PLATFORM(COCOA) // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. // We use SharedBuffer's ability to wrap itself inside CFData to get around this, ensuring that ImageIO is // really looking at the SharedBuffer. CGImageSourceUpdateData(m_nativeDecoder.get(), data.createCFData().get(), allDataReceived); #else // Create a CGDataProvider to wrap the SharedBuffer. data.ref(); // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer // does not provide a way to lock down the byte pointer and guarantee that it won't move, which // is a requirement for using the GetBytePointer callback. CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease }; RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateDirect(&data, data.size(), &providerCallbacks)); CGImageSourceUpdateDataProvider(m_nativeDecoder.get(), dataProvider.get(), allDataReceived); #endif }
std::unique_ptr<FontCustomPlatformData> createFontCustomPlatformData(SharedBuffer& buffer) { RetainPtr<CFDataRef> bufferData = buffer.createCFData(); #if CORETEXT_WEB_FONTS RetainPtr<CTFontDescriptorRef> fontDescriptor = adoptCF(CTFontManagerCreateFontDescriptorFromData(bufferData.get())); if (!fontDescriptor) return nullptr; return std::make_unique<FontCustomPlatformData>(fontDescriptor.get()); #else RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(bufferData.get())); RetainPtr<CGFontRef> cgFontRef = adoptCF(CGFontCreateWithDataProvider(dataProvider.get())); if (!cgFontRef) return nullptr; return std::make_unique<FontCustomPlatformData>(cgFontRef.get()); #endif }
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; }