blob: 87f4eb1eba2872e0cb0ab95916afede29fcba244 [file] [log] [blame]
/*
* Copyright (C) 2016-2021 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 INC. 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 INC. 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 "WebCoreArgumentCoders.h"
#import "ArgumentCodersCF.h"
#import "ArgumentCodersCocoa.h"
#import <CoreText/CoreText.h>
#import <WebCore/AttributedString.h>
#import <WebCore/DataDetectorElementInfo.h>
#import <WebCore/DictionaryPopupInfo.h>
#import <WebCore/Font.h>
#import <WebCore/FontAttributes.h>
#import <WebCore/FontCustomPlatformData.h>
#import <WebCore/ResourceRequest.h>
#import <WebCore/TextRecognitionResult.h>
#import <pal/spi/cf/CoreTextSPI.h>
#if PLATFORM(IOS_FAMILY)
#import <UIKit/UIFont.h>
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
#import <WebCore/MediaPlaybackTargetContext.h>
#import <objc/runtime.h>
#endif
#if USE(APPLE_INTERNAL_SDK)
#include <WebKitAdditions/WebCoreArgumentCodersCocoaAdditions.mm>
#endif
#if USE(AVFOUNDATION)
#import <wtf/MachSendRight.h>
#endif
#if ENABLE(APPLE_PAY)
#import "DataReference.h"
#import <WebCore/PaymentAuthorizationStatus.h>
#import <pal/cocoa/PassKitSoftLink.h>
#endif
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
#import <pal/cocoa/AVFoundationSoftLink.h>
#endif
#if ENABLE(DATA_DETECTION)
#import <pal/cocoa/DataDetectorsCoreSoftLink.h>
#endif
#if USE(AVFOUNDATION)
#import <WebCore/CoreVideoSoftLink.h>
#endif
namespace IPC {
void ArgumentCoder<WebCore::AttributedString>::encode(Encoder& encoder, const WebCore::AttributedString& attributedString)
{
encoder << attributedString.string << attributedString.documentAttributes;
}
std::optional<WebCore::AttributedString> ArgumentCoder<WebCore::AttributedString>::decode(Decoder& decoder)
{
RetainPtr<NSAttributedString> attributedString;
if (!IPC::decode(decoder, attributedString))
return std::nullopt;
RetainPtr<NSDictionary> documentAttributes;
if (!IPC::decode(decoder, documentAttributes))
return std::nullopt;
return { { WTFMove(attributedString), WTFMove(documentAttributes) } };
}
#if ENABLE(APPLE_PAY)
#if HAVE(PASSKIT_INSTALLMENTS)
void ArgumentCoder<WebCore::PaymentInstallmentConfiguration>::encode(Encoder& encoder, const WebCore::PaymentInstallmentConfiguration& configuration)
{
encoder << configuration.platformConfiguration();
}
std::optional<WebCore::PaymentInstallmentConfiguration> ArgumentCoder<WebCore::PaymentInstallmentConfiguration>::decode(Decoder& decoder)
{
auto configuration = IPC::decode<PKPaymentInstallmentConfiguration>(decoder, PAL::getPKPaymentInstallmentConfigurationClass());
if (!configuration)
return std::nullopt;
return { WTFMove(*configuration) };
}
#endif // HAVE(PASSKIT_INSTALLMENTS)
void ArgumentCoder<WebCore::Payment>::encode(Encoder& encoder, const WebCore::Payment& payment)
{
encoder << payment.pkPayment();
}
std::optional<WebCore::Payment> ArgumentCoder<WebCore::Payment>::decode(Decoder& decoder)
{
auto payment = IPC::decode<PKPayment>(decoder, PAL::getPKPaymentClass());
if (!payment)
return std::nullopt;
return WebCore::Payment { WTFMove(*payment) };
}
void ArgumentCoder<WebCore::PaymentAuthorizationResult>::encode(Encoder& encoder, const WebCore::PaymentAuthorizationResult& result)
{
encoder << result.status;
encoder << result.errors;
}
std::optional<WebCore::PaymentAuthorizationResult> ArgumentCoder<WebCore::PaymentAuthorizationResult>::decode(Decoder& decoder)
{
std::optional<WebCore::PaymentAuthorizationStatus> status;
decoder >> status;
if (!status)
return std::nullopt;
std::optional<Vector<RefPtr<WebCore::ApplePayError>>> errors;
decoder >> errors;
if (!errors)
return std::nullopt;
return {{ WTFMove(*status), WTFMove(*errors) }};
}
void ArgumentCoder<WebCore::PaymentContact>::encode(Encoder& encoder, const WebCore::PaymentContact& paymentContact)
{
encoder << paymentContact.pkContact();
}
std::optional<WebCore::PaymentContact> ArgumentCoder<WebCore::PaymentContact>::decode(Decoder& decoder)
{
auto contact = IPC::decode<PKContact>(decoder, PAL::getPKContactClass());
if (!contact)
return std::nullopt;
return WebCore::PaymentContact { WTFMove(*contact) };
}
void ArgumentCoder<WebCore::PaymentMerchantSession>::encode(Encoder& encoder, const WebCore::PaymentMerchantSession& paymentMerchantSession)
{
encoder << paymentMerchantSession.pkPaymentMerchantSession();
}
std::optional<WebCore::PaymentMerchantSession> ArgumentCoder<WebCore::PaymentMerchantSession>::decode(Decoder& decoder)
{
auto paymentMerchantSession = IPC::decode<PKPaymentMerchantSession>(decoder, PAL::getPKPaymentMerchantSessionClass());
if (!paymentMerchantSession)
return std::nullopt;
return WebCore::PaymentMerchantSession { WTFMove(*paymentMerchantSession) };
}
void ArgumentCoder<WebCore::PaymentMethod>::encode(Encoder& encoder, const WebCore::PaymentMethod& paymentMethod)
{
encoder << paymentMethod.pkPaymentMethod();
}
std::optional<WebCore::PaymentMethod> ArgumentCoder<WebCore::PaymentMethod>::decode(Decoder& decoder)
{
auto paymentMethod = IPC::decode<PKPaymentMethod>(decoder, PAL::getPKPaymentMethodClass());
if (!paymentMethod)
return std::nullopt;
return WebCore::PaymentMethod { WTFMove(*paymentMethod) };
}
void ArgumentCoder<WebCore::ApplePaySessionPaymentRequest>::encode(Encoder& encoder, const WebCore::ApplePaySessionPaymentRequest& request)
{
encoder << request.countryCode();
encoder << request.currencyCode();
encoder << request.requiredBillingContactFields();
encoder << request.billingContact();
encoder << request.requiredShippingContactFields();
encoder << request.shippingContact();
encoder << request.merchantCapabilities();
encoder << request.supportedNetworks();
encoder << request.shippingType();
encoder << request.shippingMethods();
encoder << request.lineItems();
encoder << request.total();
encoder << request.applicationData();
encoder << request.supportedCountries();
encoder << request.requester();
#if ENABLE(APPLE_PAY_INSTALLMENTS)
encoder << request.installmentConfiguration();
#endif
#if ENABLE(APPLE_PAY_COUPON_CODE)
encoder << request.supportsCouponCode();
encoder << request.couponCode();
#endif
#if ENABLE(APPLE_PAY_SHIPPING_CONTACT_EDITING_MODE)
encoder << request.shippingContactEditingMode();
#endif
#if defined(WebCoreArgumentCodersCocoaAdditions_ApplePaySessionPaymentRequest_encode)
WebCoreArgumentCodersCocoaAdditions_ApplePaySessionPaymentRequest_encode
#endif
}
bool ArgumentCoder<WebCore::ApplePaySessionPaymentRequest>::decode(Decoder& decoder, WebCore::ApplePaySessionPaymentRequest& request)
{
String countryCode;
if (!decoder.decode(countryCode))
return false;
request.setCountryCode(countryCode);
String currencyCode;
if (!decoder.decode(currencyCode))
return false;
request.setCurrencyCode(currencyCode);
WebCore::ApplePaySessionPaymentRequest::ContactFields requiredBillingContactFields;
if (!decoder.decode((requiredBillingContactFields)))
return false;
request.setRequiredBillingContactFields(requiredBillingContactFields);
std::optional<WebCore::PaymentContact> billingContact;
decoder >> billingContact;
if (!billingContact)
return false;
request.setBillingContact(*billingContact);
WebCore::ApplePaySessionPaymentRequest::ContactFields requiredShippingContactFields;
if (!decoder.decode((requiredShippingContactFields)))
return false;
request.setRequiredShippingContactFields(requiredShippingContactFields);
std::optional<WebCore::PaymentContact> shippingContact;
decoder >> shippingContact;
if (!shippingContact)
return false;
request.setShippingContact(*shippingContact);
WebCore::ApplePaySessionPaymentRequest::MerchantCapabilities merchantCapabilities;
if (!decoder.decode(merchantCapabilities))
return false;
request.setMerchantCapabilities(merchantCapabilities);
Vector<String> supportedNetworks;
if (!decoder.decode(supportedNetworks))
return false;
request.setSupportedNetworks(supportedNetworks);
WebCore::ApplePaySessionPaymentRequest::ShippingType shippingType;
if (!decoder.decode(shippingType))
return false;
request.setShippingType(shippingType);
Vector<WebCore::ApplePayShippingMethod> shippingMethods;
if (!decoder.decode(shippingMethods))
return false;
request.setShippingMethods(shippingMethods);
Vector<WebCore::ApplePayLineItem> lineItems;
if (!decoder.decode(lineItems))
return false;
request.setLineItems(lineItems);
std::optional<WebCore::ApplePayLineItem> total;
decoder >> total;
if (!total)
return false;
request.setTotal(*total);
String applicationData;
if (!decoder.decode(applicationData))
return false;
request.setApplicationData(applicationData);
Vector<String> supportedCountries;
if (!decoder.decode(supportedCountries))
return false;
request.setSupportedCountries(WTFMove(supportedCountries));
WebCore::ApplePaySessionPaymentRequest::Requester requester;
if (!decoder.decode(requester))
return false;
request.setRequester(requester);
#if ENABLE(APPLE_PAY_INSTALLMENTS)
std::optional<WebCore::PaymentInstallmentConfiguration> installmentConfiguration;
decoder >> installmentConfiguration;
if (!installmentConfiguration)
return false;
request.setInstallmentConfiguration(WTFMove(*installmentConfiguration));
#endif
#if ENABLE(APPLE_PAY_COUPON_CODE)
std::optional<std::optional<bool>> supportsCouponCode;
decoder >> supportsCouponCode;
if (!supportsCouponCode)
return false;
request.setSupportsCouponCode(WTFMove(*supportsCouponCode));
std::optional<String> couponCode;
decoder >> couponCode;
if (!couponCode)
return false;
request.setCouponCode(WTFMove(*couponCode));
#endif
#if ENABLE(APPLE_PAY_SHIPPING_CONTACT_EDITING_MODE)
std::optional<std::optional<WebCore::ApplePayShippingContactEditingMode>> shippingContactEditingMode;
decoder >> shippingContactEditingMode;
if (!shippingContactEditingMode)
return false;
request.setShippingContactEditingMode(WTFMove(*shippingContactEditingMode));
#endif
#if defined(WebCoreArgumentCodersCocoaAdditions_ApplePaySessionPaymentRequest_decode)
WebCoreArgumentCodersCocoaAdditions_ApplePaySessionPaymentRequest_decode
#endif
return true;
}
void ArgumentCoder<WebCore::ApplePaySessionPaymentRequest::ContactFields>::encode(Encoder& encoder, const WebCore::ApplePaySessionPaymentRequest::ContactFields& contactFields)
{
encoder << contactFields.postalAddress;
encoder << contactFields.phone;
encoder << contactFields.email;
encoder << contactFields.name;
encoder << contactFields.phoneticName;
}
bool ArgumentCoder<WebCore::ApplePaySessionPaymentRequest::ContactFields>::decode(Decoder& decoder, WebCore::ApplePaySessionPaymentRequest::ContactFields& contactFields)
{
if (!decoder.decode(contactFields.postalAddress))
return false;
if (!decoder.decode(contactFields.phone))
return false;
if (!decoder.decode(contactFields.email))
return false;
if (!decoder.decode(contactFields.name))
return false;
if (!decoder.decode(contactFields.phoneticName))
return false;
return true;
}
void ArgumentCoder<WebCore::ApplePaySessionPaymentRequest::MerchantCapabilities>::encode(Encoder& encoder, const WebCore::ApplePaySessionPaymentRequest::MerchantCapabilities& merchantCapabilities)
{
encoder << merchantCapabilities.supports3DS;
encoder << merchantCapabilities.supportsEMV;
encoder << merchantCapabilities.supportsCredit;
encoder << merchantCapabilities.supportsDebit;
}
bool ArgumentCoder<WebCore::ApplePaySessionPaymentRequest::MerchantCapabilities>::decode(Decoder& decoder, WebCore::ApplePaySessionPaymentRequest::MerchantCapabilities& merchantCapabilities)
{
if (!decoder.decode(merchantCapabilities.supports3DS))
return false;
if (!decoder.decode(merchantCapabilities.supportsEMV))
return false;
if (!decoder.decode(merchantCapabilities.supportsCredit))
return false;
if (!decoder.decode(merchantCapabilities.supportsDebit))
return false;
return true;
}
void ArgumentCoder<RefPtr<WebCore::ApplePayError>>::encode(Encoder& encoder, const RefPtr<WebCore::ApplePayError>& error)
{
encoder << !!error;
if (error)
encoder << *error;
}
std::optional<RefPtr<WebCore::ApplePayError>> ArgumentCoder<RefPtr<WebCore::ApplePayError>>::decode(Decoder& decoder)
{
std::optional<bool> isValid;
decoder >> isValid;
if (!isValid)
return std::nullopt;
RefPtr<WebCore::ApplePayError> error;
if (!*isValid)
return { nullptr };
error = WebCore::ApplePayError::decode(decoder);
if (!error)
return std::nullopt;
return error;
}
void ArgumentCoder<WebCore::PaymentSessionError>::encode(Encoder& encoder, const WebCore::PaymentSessionError& error)
{
encoder << error.platformError();
}
std::optional<WebCore::PaymentSessionError> ArgumentCoder<WebCore::PaymentSessionError>::decode(Decoder& decoder)
{
auto platformError = IPC::decode<NSError>(decoder);
if (!platformError)
return std::nullopt;
return { WTFMove(*platformError) };
}
#endif // ENABLE(APPLEPAY)
void ArgumentCoder<WebCore::DictionaryPopupInfo>::encodePlatformData(Encoder& encoder, const WebCore::DictionaryPopupInfo& info)
{
encoder << info.options << info.attributedString;
}
bool ArgumentCoder<WebCore::DictionaryPopupInfo>::decodePlatformData(Decoder& decoder, WebCore::DictionaryPopupInfo& result)
{
if (!IPC::decode(decoder, result.options))
return false;
if (!IPC::decode(decoder, result.attributedString))
return false;
return true;
}
void ArgumentCoder<WebCore::FontAttributes>::encodePlatformData(Encoder& encoder, const WebCore::FontAttributes& attributes)
{
encoder << attributes.font;
}
std::optional<WebCore::FontAttributes> ArgumentCoder<WebCore::FontAttributes>::decodePlatformData(Decoder& decoder, WebCore::FontAttributes& attributes)
{
if (!IPC::decode(decoder, attributes.font))
return std::nullopt;
return attributes;
}
void ArgumentCoder<Ref<WebCore::Font>>::encodePlatformData(Encoder& encoder, const Ref<WebCore::Font>& font)
{
const auto& platformData = font->platformData();
encoder << platformData.orientation();
encoder << platformData.widthVariant();
encoder << platformData.textRenderingMode();
encoder << platformData.size();
encoder << platformData.syntheticBold();
encoder << platformData.syntheticOblique();
auto ctFont = platformData.font();
auto fontDescriptor = adoptCF(CTFontCopyFontDescriptor(ctFont));
auto attributes = adoptCF(CTFontDescriptorCopyAttributes(fontDescriptor.get()));
encoder << attributes;
const auto& creationData = platformData.creationData();
encoder << static_cast<bool>(creationData);
if (creationData) {
encoder << creationData->fontFaceData;
encoder << creationData->itemInCollection;
} else {
auto referenceURL = adoptCF(static_cast<CFURLRef>(CTFontCopyAttribute(ctFont, kCTFontReferenceURLAttribute)));
auto string = CFURLGetString(referenceURL.get());
encoder << String(string);
encoder << String(adoptCF(CTFontCopyPostScriptName(ctFont)).get());
}
}
static RetainPtr<CTFontDescriptorRef> findFontDescriptor(const String& referenceURL, const String& postScriptName)
{
auto url = adoptCF(CFURLCreateWithString(kCFAllocatorDefault, referenceURL.createCFString().get(), nullptr));
if (!url)
return nullptr;
auto fontDescriptors = adoptCF(CTFontManagerCreateFontDescriptorsFromURL(url.get()));
if (!fontDescriptors || !CFArrayGetCount(fontDescriptors.get()))
return nullptr;
if (CFArrayGetCount(fontDescriptors.get()) == 1)
return static_cast<CTFontDescriptorRef>(CFArrayGetValueAtIndex(fontDescriptors.get(), 0));
for (CFIndex i = 0; i < CFArrayGetCount(fontDescriptors.get()); ++i) {
auto fontDescriptor = static_cast<CTFontDescriptorRef>(CFArrayGetValueAtIndex(fontDescriptors.get(), i));
auto currentPostScriptName = adoptCF(static_cast<CFStringRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontNameAttribute)));
if (String(currentPostScriptName.get()) == postScriptName)
return fontDescriptor;
}
return nullptr;
}
static RetainPtr<CTFontRef> createCTFont(CFDictionaryRef attributes, float size, const String& referenceURL, const String& desiredPostScriptName)
{
auto fontDescriptor = adoptCF(CTFontDescriptorCreateWithAttributes(attributes));
if (fontDescriptor) {
auto font = adoptCF(CTFontCreateWithFontDescriptorAndOptions(fontDescriptor.get(), size, nullptr, kCTFontOptionsSystemUIFont));
String actualPostScriptName(adoptCF(CTFontCopyPostScriptName(font.get())).get());
if (actualPostScriptName == desiredPostScriptName)
return font;
}
// CoreText couldn't round-trip the font.
// We can fall back to doing our best to find it ourself.
fontDescriptor = findFontDescriptor(referenceURL, desiredPostScriptName);
if (!fontDescriptor) {
ASSERT_NOT_REACHED();
fontDescriptor = adoptCF(CTFontDescriptorCreateLastResort());
}
ASSERT(fontDescriptor);
return adoptCF(CTFontCreateWithFontDescriptorAndOptions(fontDescriptor.get(), size, nullptr, kCTFontOptionsSystemUIFont));
}
std::optional<WebCore::FontPlatformData> ArgumentCoder<Ref<WebCore::Font>>::decodePlatformData(Decoder& decoder)
{
std::optional<WebCore::FontOrientation> orientation;
decoder >> orientation;
if (!orientation)
return std::nullopt;
std::optional<WebCore::FontWidthVariant> widthVariant;
decoder >> widthVariant;
if (!widthVariant)
return std::nullopt;
std::optional<WebCore::TextRenderingMode> textRenderingMode;
decoder >> textRenderingMode;
if (!textRenderingMode)
return std::nullopt;
std::optional<float> size;
decoder >> size;
if (!size)
return std::nullopt;
std::optional<bool> syntheticBold;
decoder >> syntheticBold;
if (!syntheticBold)
return std::nullopt;
std::optional<bool> syntheticOblique;
decoder >> syntheticOblique;
if (!syntheticOblique)
return std::nullopt;
std::optional<RetainPtr<CFDictionaryRef>> attributes;
decoder >> attributes;
if (!attributes)
return std::nullopt;
std::optional<bool> includesCreationData;
decoder >> includesCreationData;
if (!includesCreationData)
return std::nullopt;
if (*includesCreationData) {
std::optional<Ref<WebCore::SharedBuffer>> fontFaceData;
decoder >> fontFaceData;
if (!fontFaceData)
return std::nullopt;
// Upon receipt, copy the data for security, so the sender can't scribble over it while we're using it.
auto localFontFaceData = WebCore::SharedBuffer::create(fontFaceData.value()->data(), fontFaceData.value()->size());
std::optional<String> itemInCollection;
decoder >> itemInCollection;
if (!itemInCollection)
return std::nullopt;
auto fontCustomPlatformData = createFontCustomPlatformData(localFontFaceData, *itemInCollection);
if (!fontCustomPlatformData)
return std::nullopt;
auto baseFontDescriptor = fontCustomPlatformData->fontDescriptor.get();
if (!baseFontDescriptor)
return std::nullopt;
auto fontDescriptor = adoptCF(CTFontDescriptorCreateCopyWithAttributes(baseFontDescriptor, attributes->get()));
auto ctFont = adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), *size, nullptr));
auto creationData = WebCore::FontPlatformData::CreationData { localFontFaceData, *itemInCollection };
return WebCore::FontPlatformData(ctFont.get(), *size, *syntheticBold, *syntheticOblique, *orientation, *widthVariant, *textRenderingMode, &creationData);
}
std::optional<String> referenceURL;
decoder >> referenceURL;
if (!referenceURL)
return std::nullopt;
std::optional<String> postScriptName;
decoder >> postScriptName;
if (!postScriptName)
return std::nullopt;
auto ctFont = createCTFont(attributes->get(), *size, *referenceURL, *postScriptName);
if (!ctFont)
return std::nullopt;
return WebCore::FontPlatformData(ctFont.get(), *size, *syntheticBold, *syntheticOblique, *orientation, *widthVariant, *textRenderingMode);
}
void ArgumentCoder<WebCore::ResourceRequest>::encodePlatformData(Encoder& encoder, const WebCore::ResourceRequest& resourceRequest)
{
auto requestToSerialize = retainPtr(resourceRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody));
if (Class requestClass = [requestToSerialize class]; UNLIKELY(requestClass != [NSURLRequest class] && requestClass != [NSMutableURLRequest class])) {
WebCore::ResourceRequest request(requestToSerialize.get());
request.replacePlatformRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
requestToSerialize = retainPtr(request.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody));
}
ASSERT([requestToSerialize class] == [NSURLRequest class] || [requestToSerialize class] == [NSMutableURLRequest class]);
bool requestIsPresent = requestToSerialize;
encoder << requestIsPresent;
if (!requestIsPresent)
return;
// We don't send HTTP body over IPC for better performance.
// Also, it's not always possible to do, as streams can only be created in process that does networking.
if ([requestToSerialize HTTPBody] || [requestToSerialize HTTPBodyStream]) {
auto mutableRequest = adoptNS([requestToSerialize mutableCopy]);
[mutableRequest setHTTPBody:nil];
[mutableRequest setHTTPBodyStream:nil];
requestToSerialize = WTFMove(mutableRequest);
}
IPC::encode(encoder, requestToSerialize.get());
encoder << resourceRequest.requester();
encoder << resourceRequest.isAppInitiated();
}
bool ArgumentCoder<WebCore::ResourceRequest>::decodePlatformData(Decoder& decoder, WebCore::ResourceRequest& resourceRequest)
{
bool requestIsPresent;
if (!decoder.decode(requestIsPresent))
return false;
if (!requestIsPresent) {
resourceRequest = WebCore::ResourceRequest();
return true;
}
auto request = IPC::decode<NSURLRequest>(decoder, NSURLRequest.class);
if (!request)
return false;
WebCore::ResourceRequest::Requester requester;
if (!decoder.decode(requester))
return false;
bool isAppInitiated;
if (!decoder.decode(isAppInitiated))
return false;
resourceRequest = WebCore::ResourceRequest(request->get());
resourceRequest.setRequester(requester);
resourceRequest.setIsAppInitiated(isAppInitiated);
return true;
}
#if ENABLE(DATA_DETECTION)
void ArgumentCoder<WebCore::DataDetectorElementInfo>::encode(Encoder& encoder, const WebCore::DataDetectorElementInfo& info)
{
encoder << info.result.get();
encoder << info.elementBounds;
}
std::optional<WebCore::DataDetectorElementInfo> ArgumentCoder<WebCore::DataDetectorElementInfo>::decode(Decoder& decoder)
{
auto result = IPC::decode<DDScannerResult>(decoder, PAL::getDDScannerResultClass());
if (!result)
return std::nullopt;
std::optional<WebCore::IntRect> elementBounds;
decoder >> elementBounds;
if (!elementBounds)
return std::nullopt;
return std::make_optional<WebCore::DataDetectorElementInfo>({ WTFMove(*result), WTFMove(*elementBounds) });
}
#endif // ENABLE(DATA_DETECTION)
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
void ArgumentCoder<WebCore::MediaPlaybackTargetContext>::encodePlatformData(Encoder& encoder, const WebCore::MediaPlaybackTargetContext& target)
{
if (target.type() == WebCore::MediaPlaybackTargetContext::Type::AVOutputContext) {
if ([PAL::getAVOutputContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
encoder << target.outputContext();
} else if (target.type() == WebCore::MediaPlaybackTargetContext::Type::SerializedAVOutputContext) {
encoder << target.serializedOutputContext();
encoder << target.hasActiveRoute();
} else
ASSERT_NOT_REACHED();
}
bool ArgumentCoder<WebCore::MediaPlaybackTargetContext>::decodePlatformData(Decoder& decoder, WebCore::MediaPlaybackTargetContext::Type contextType, WebCore::MediaPlaybackTargetContext& target)
{
ASSERT(contextType != WebCore::MediaPlaybackTargetContext::Type::Mock);
if (contextType == WebCore::MediaPlaybackTargetContext::Type::AVOutputContext) {
if (![PAL::getAVOutputContextClass() conformsToProtocol:@protocol(NSSecureCoding)])
return false;
auto outputContext = IPC::decode<AVOutputContext>(decoder, PAL::getAVOutputContextClass());
if (!outputContext)
return false;
target = WebCore::MediaPlaybackTargetContext { WTFMove(*outputContext) };
return true;
}
if (contextType == WebCore::MediaPlaybackTargetContext::Type::SerializedAVOutputContext) {
RetainPtr<NSData> serializedOutputContext;
if (!IPC::decode(decoder, serializedOutputContext) || !serializedOutputContext)
return false;
bool hasActiveRoute;
if (!decoder.decode(hasActiveRoute))
return false;
target = WebCore::MediaPlaybackTargetContext { WTFMove(serializedOutputContext), hasActiveRoute };
return true;
}
return false;
}
#endif
#if ENABLE(IMAGE_ANALYSIS) && ENABLE(DATA_DETECTION)
void ArgumentCoder<WebCore::TextRecognitionDataDetector>::encodePlatformData(Encoder& encoder, const WebCore::TextRecognitionDataDetector& info)
{
encoder << info.result.get();
}
bool ArgumentCoder<WebCore::TextRecognitionDataDetector>::decodePlatformData(Decoder& decoder, WebCore::TextRecognitionDataDetector& result)
{
auto scannerResult = IPC::decode<DDScannerResult>(decoder, @[ PAL::getDDScannerResultClass() ]);
if (!scannerResult)
return false;
result.result = WTFMove(*scannerResult);
return true;
}
#endif // ENABLE(IMAGE_ANALYSIS) && ENABLE(DATA_DETECTION)
#if USE(AVFOUNDATION)
void ArgumentCoder<RetainPtr<CVPixelBufferRef>>::encode(Encoder& encoder, const RetainPtr<CVPixelBufferRef>& pixelBuffer)
{
// Use IOSurface as the means to transfer CVPixelBufferRef.
MachSendRight sendRight;
if (pixelBuffer) {
if (auto surface = WebCore::CVPixelBufferGetIOSurface(pixelBuffer.get()))
sendRight = MachSendRight::adopt(IOSurfaceCreateMachPort(surface));
}
encoder << WTFMove(sendRight);
}
std::optional<RetainPtr<CVPixelBufferRef>> ArgumentCoder<RetainPtr<CVPixelBufferRef>>::decode(Decoder& decoder)
{
std::optional<MachSendRight> sendRight;
decoder >> sendRight;
if (!sendRight)
return std::nullopt;
RetainPtr<CVPixelBufferRef> pixelBuffer;
if (!*sendRight)
return pixelBuffer;
{
auto surface = adoptCF(IOSurfaceLookupFromMachPort(sendRight->sendRight()));
if (!surface)
return std::nullopt;
CVPixelBufferRef rawBuffer = nullptr;
auto status = WebCore::CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, surface.get(), nullptr, &rawBuffer);
if (status != noErr || !rawBuffer)
return std::nullopt;
pixelBuffer = adoptCF(rawBuffer);
}
return pixelBuffer;
}
#endif
} // namespace IPC