static RetainPtr<CFDataRef> encodeSessionHistoryEntryData(const FrameState& frameState) { static CFAllocatorRef fastMallocDeallocator; static std::once_flag onceFlag; std::call_once(onceFlag, [] { CFAllocatorContext context = { 0, // version nullptr, // info nullptr, // retain nullptr, // release nullptr, // copyDescription nullptr, // allocate nullptr, // reallocate [](void *ptr, void *info) { WTF::fastFree(ptr); }, nullptr, // preferredSize }; fastMallocDeallocator = CFAllocatorCreate(kCFAllocatorDefault, &context); }); size_t bufferSize; auto buffer = encodeSessionHistoryEntryData(frameState, bufferSize); return adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, buffer.leakPtr(), bufferSize, fastMallocDeallocator)); }
static RetainPtr<CFDictionaryRef> encodeSessionHistory(const BackForwardListState& backForwardListState) { ASSERT(!backForwardListState.currentIndex || backForwardListState.currentIndex.value() < backForwardListState.items.size()); auto sessionHistoryVersionNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sessionHistoryVersion)); if (!backForwardListState.currentIndex) return createDictionary({ { sessionHistoryVersionKey, sessionHistoryVersionNumber.get() } }); auto entries = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, backForwardListState.items.size(), &kCFTypeArrayCallBacks)); for (const auto& item : backForwardListState.items) { auto url = item.pageState.mainFrameState.urlString.createCFString(); auto title = item.pageState.title.createCFString(); auto originalURL = item.pageState.mainFrameState.originalURLString.createCFString(); auto data = encodeSessionHistoryEntryData(item.pageState.mainFrameState); auto entryDictionary = createDictionary({ { sessionHistoryEntryURLKey, url.get() }, { sessionHistoryEntryTitleKey, title.get() }, { sessionHistoryEntryOriginalURLKey, originalURL.get() }, { sessionHistoryEntryDataKey, data.get() } }); CFArrayAppendValue(entries.get(), entryDictionary.get()); } uint32_t currentIndex = backForwardListState.currentIndex.value(); auto currentIndexNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, ¤tIndex)); return createDictionary({ { sessionHistoryVersionKey, sessionHistoryVersionNumber.get() }, { sessionHistoryCurrentIndexKey, currentIndexNumber.get() }, { sessionHistoryEntriesKey, entries.get() } }); }
static RetainPtr<CFDictionaryRef> encodeSessionHistory(const BackForwardListState& backForwardListState) { ASSERT(!backForwardListState.currentIndex || backForwardListState.currentIndex.value() < backForwardListState.items.size()); auto sessionHistoryVersionNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sessionHistoryVersion)); if (!backForwardListState.currentIndex) return createDictionary({ { sessionHistoryVersionKey, sessionHistoryVersionNumber.get() } }); auto entries = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, backForwardListState.items.size(), &kCFTypeArrayCallBacks)); size_t totalDataSize = 0; for (const auto& item : backForwardListState.items) { auto url = item.pageState.mainFrameState.urlString.createCFString(); auto title = item.pageState.title.createCFString(); auto originalURL = item.pageState.mainFrameState.originalURLString.createCFString(); auto data = totalDataSize <= maximumSessionStateDataSize ? encodeSessionHistoryEntryData(item.pageState.mainFrameState) : nullptr; auto shouldOpenExternalURLsPolicyValue = static_cast<uint64_t>(item.pageState.shouldOpenExternalURLsPolicy); auto shouldOpenExternalURLsPolicy = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &shouldOpenExternalURLsPolicyValue)); RetainPtr<CFDictionaryRef> entryDictionary; if (data) { totalDataSize += CFDataGetLength(data.get()); entryDictionary = createDictionary({ { sessionHistoryEntryURLKey, url.get() }, { sessionHistoryEntryTitleKey, title.get() }, { sessionHistoryEntryOriginalURLKey, originalURL.get() }, { sessionHistoryEntryDataKey, data.get() }, { sessionHistoryEntryShouldOpenExternalURLsPolicyKey, shouldOpenExternalURLsPolicy.get() }, }); } else { entryDictionary = createDictionary({ { sessionHistoryEntryURLKey, url.get() }, { sessionHistoryEntryTitleKey, title.get() }, { sessionHistoryEntryOriginalURLKey, originalURL.get() }, { sessionHistoryEntryShouldOpenExternalURLsPolicyKey, shouldOpenExternalURLsPolicy.get() }, }); } CFArrayAppendValue(entries.get(), entryDictionary.get()); } uint32_t currentIndex = backForwardListState.currentIndex.value(); auto currentIndexNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, ¤tIndex)); return createDictionary({ { sessionHistoryVersionKey, sessionHistoryVersionNumber.get() }, { sessionHistoryCurrentIndexKey, currentIndexNumber.get() }, { sessionHistoryEntriesKey, entries.get() } }); }