Modified: trunk/Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm (273540 => 273541)
--- trunk/Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm 2021-02-26 03:58:52 UTC (rev 273540)
+++ trunk/Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm 2021-02-26 05:06:47 UTC (rev 273541)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-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
@@ -36,6 +36,8 @@
#import <CoreText/CTFontDescriptor.h>
#import <wtf/BlockObjCExceptions.h>
#import <wtf/HashSet.h>
+#import <wtf/cf/CFURLExtras.h>
+#import <wtf/cocoa/NSURLExtras.h>
#if USE(APPKIT)
#import <WebCore/ColorMac.h>
@@ -49,29 +51,112 @@
#import <UIKit/UIFontDescriptor.h>
#endif
-#if HAVE(NSFONT_WITH_OPTICAL_SIZING_BUG)
+NS_ASSUME_NONNULL_BEGIN
-@interface WKSecureCodingFontAttributeNormalizer : NSObject <NSKeyedArchiverDelegate>
+@interface WKSecureCodingArchivingDelegate : NSObject <NSKeyedArchiverDelegate, NSKeyedUnarchiverDelegate>
@end
-@implementation WKSecureCodingFontAttributeNormalizer
+@interface WKSecureCodingURLWrapper : NSObject <NSSecureCoding>
+- (instancetype _Nullable)initWithURL:(NSURL *)wrappedURL;
+@property (nonatomic, readonly) NSURL * wrappedURL;
+@end
-- (id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object
+@implementation WKSecureCodingArchivingDelegate
+
+- (nullable id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object
{
- if ([object isKindOfClass:[NSFont class]]) {
- NSFont *font = static_cast<NSFont *>(object);
+#if HAVE(NSFONT_WITH_OPTICAL_SIZING_BUG)
+ if (auto font = dynamic_objc_cast<NSFont>(object)) {
// Recreate any serialized fonts after normalizing the
// font attributes to work around <rdar://problem/51657880>.
return WebKit::fontWithAttributes(font.fontDescriptor.fontAttributes, 0);
}
+#endif
+ if (auto unwrappedURL = dynamic_objc_cast<NSURL>(object))
+ return adoptNS([[WKSecureCodingURLWrapper alloc] initWithURL:unwrappedURL]).autorelease();
+
return object;
}
+- (id _Nullable)unarchiver:(NSKeyedUnarchiver *)unarchiver didDecodeObject:(id _Nullable) NS_RELEASES_ARGUMENT object NS_RETURNS_RETAINED
+{
+ auto adoptedObject = adoptNS(object);
+ if (auto wrapper = dynamic_objc_cast<WKSecureCodingURLWrapper>(adoptedObject.get()))
+ return retainPtr(wrapper.wrappedURL).leakRef();
+
+ return adoptedObject.leakRef();
+}
+
@end
-#endif
+@implementation WKSecureCodingURLWrapper {
+ RetainPtr<NSURL> m_wrappedURL;
+}
+- (NSURL *)wrappedURL
+{
+ return m_wrappedURL.get();
+}
+
++ (BOOL)supportsSecureCoding
+{
+ return YES;
+}
+
+static constexpr NSString *baseURLKey = @"WK.baseURL";
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ RELEASE_ASSERT(m_wrappedURL);
+ auto baseURL = m_wrappedURL.get().baseURL;
+ BOOL hasBaseURL = !!baseURL;
+
+ [coder encodeValueOfObjCType:"c" at:&hasBaseURL];
+ if (hasBaseURL)
+ [coder encodeObject:baseURL forKey:baseURLKey];
+
+ WTF::URLCharBuffer urlBytes;
+ WTF::getURLBytes((__bridge CFURLRef)m_wrappedURL.get(), urlBytes);
+ [coder encodeBytes:urlBytes.data() length:urlBytes.size()];
+}
+
+- (_Nullable instancetype)initWithCoder:(NSCoder *)coder
+{
+ auto selfPtr = adoptNS([super init]);
+ if (!selfPtr)
+ return nil;
+
+ BOOL hasBaseURL;
+ [coder decodeValueOfObjCType:"c" at:&hasBaseURL size:sizeof(hasBaseURL)];
+
+ RetainPtr<NSURL> baseURL;
+ if (hasBaseURL)
+ baseURL = (NSURL *)[coder decodeObjectOfClass:NSURL.class forKey:baseURLKey];
+
+ NSUInteger length;
+ if (auto bytes = (UInt8 *)[coder decodeBytesWithReturnedLength:&length]) {
+ m_wrappedURL = adoptNS((__bridge NSURL*)CFURLCreateAbsoluteURLWithBytes(nullptr, bytes, length, kCFStringEncodingUTF8, (__bridge CFURLRef)baseURL.get(), true));
+ if (!m_wrappedURL)
+ LOG_ERROR("Failed to decode NSURL due to invalid encoding of length %d. Substituting a blank URL", length);
+ }
+
+ if (!m_wrappedURL)
+ m_wrappedURL = [NSURL URLWithString:@""];
+
+ return selfPtr.leakRef();
+}
+
+- (_Nullable instancetype)initWithURL:(NSURL *)url
+{
+ if (self = [super init])
+ m_wrappedURL = url;
+
+ return self;
+}
+
+@end
+
namespace IPC {
using namespace WebCore;
@@ -346,17 +431,12 @@
{
auto archiver = adoptNS([[NSKeyedArchiver alloc] initRequiringSecureCoding:YES]);
-#if HAVE(NSFONT_WITH_OPTICAL_SIZING_BUG)
- auto delegate = adoptNS([[WKSecureCodingFontAttributeNormalizer alloc] init]);
+ auto delegate = adoptNS([[WKSecureCodingArchivingDelegate alloc] init]);
[archiver setDelegate:delegate.get()];
-#endif
[archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey];
[archiver finishEncoding];
-
-#if HAVE(NSFONT_WITH_OPTICAL_SIZING_BUG)
[archiver setDelegate:nil];
-#endif
encode(encoder, (__bridge CFDataRef)[archiver encodedData]);
}
@@ -373,8 +453,15 @@
auto unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingFromData:(__bridge NSData *)data.get() error:nullptr]);
unarchiver.get().decodingFailurePolicy = NSDecodingFailurePolicyRaiseException;
+
+ auto delegate = adoptNS([[WKSecureCodingArchivingDelegate alloc] init]);
+ unarchiver.get().delegate = delegate.get();
+
+ auto allowedClassSet = adoptNS([[NSMutableSet alloc] initWithArray:allowedClasses]);
+ [allowedClassSet addObject:WKSecureCodingURLWrapper.class];
+
@try {
- id result = [unarchiver decodeObjectOfClasses:[NSSet setWithArray:allowedClasses] forKey:NSKeyedArchiveRootObjectKey];
+ id result = [unarchiver decodeObjectOfClasses:allowedClassSet.get() forKey:NSKeyedArchiveRootObjectKey];
ASSERT(!result || [result conformsToProtocol:@protocol(NSSecureCoding)]);
return { result };
} @catch (NSException *exception) {
@@ -382,6 +469,7 @@
return WTF::nullopt;
} @finally {
[unarchiver finishDecoding];
+ unarchiver.get().delegate = nil;
}
}
@@ -526,4 +614,6 @@
};
} // namespace WTF
+NS_ASSUME_NONNULL_END
+
#endif // PLATFORM(COCOA)
Modified: trunk/Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm (273540 => 273541)
--- trunk/Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm 2021-02-26 03:58:52 UTC (rev 273540)
+++ trunk/Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm 2021-02-26 05:06:47 UTC (rev 273541)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
+ * 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
@@ -34,6 +34,7 @@
#import <WebCore/Font.h>
#import <WebCore/FontAttributes.h>
#import <WebCore/FontCustomPlatformData.h>
+#import <WebCore/ResourceRequest.h>
#import <pal/spi/cf/CoreTextSPI.h>
#if PLATFORM(IOS_FAMILY)
@@ -543,4 +544,59 @@
return FontPlatformData(ctFont.get(), size.value(), syntheticBold.value(), syntheticOblique.value(), orientation.value(), widthVariant.value(), textRenderingMode.value());
}
+void ArgumentCoder<WebCore::ResourceRequest>::encodePlatformData(Encoder& encoder, const WebCore::ResourceRequest& resourceRequest)
+{
+ auto requestToSerialize = retainPtr(resourceRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody));
+
+ 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.isAppBound();
+}
+
+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 isAppBound;
+ if (!decoder.decode(isAppBound))
+ return false;
+
+ resourceRequest = WebCore::ResourceRequest(request->get());
+ resourceRequest.setRequester(requester);
+ resourceRequest.setIsAppBound(isAppBound);
+
+ return true;
+}
+
} // namespace IPC
Modified: trunk/Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm (273540 => 273541)
--- trunk/Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm 2021-02-26 03:58:52 UTC (rev 273540)
+++ trunk/Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm 2021-02-26 05:06:47 UTC (rev 273541)
@@ -42,10 +42,6 @@
#import <wtf/MachSendRight.h>
#import <wtf/cf/TypeCastsCF.h>
-#if USE(APPLE_INTERNAL_SDK)
-#include <WebKitAdditions/WebCoreArgumentCodersMacAdditions.h>
-#endif
-
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
#import <WebCore/MediaPlaybackTargetContext.h>
#import <objc/runtime.h>
@@ -52,235 +48,8 @@
#import <pal/cocoa/AVFoundationSoftLink.h>
#endif
-#ifndef WEBCORE_ARGUMENTCODERS_MAC_DECODE_ADDITIONS
-#define WEBCORE_ARGUMENTCODERS_MAC_DECODE_ADDITIONS
-#endif
-
-#ifndef WEBCORE_ARGUMENTCODERS_MAC_ENCODE_ADDITIONS
-#define WEBCORE_ARGUMENTCODERS_MAC_ENCODE_ADDITIONS
-#endif
-
namespace IPC {
-static RetainPtr<CFMutableDictionaryRef> createSerializableRepresentation(CFIndex version, CFTypeRef* objects, CFIndex objectCount, CFDictionaryRef protocolProperties, CFNumberRef expectedContentLength, CFStringRef mimeType, CFTypeRef tokenNull)
-{
- auto archiveListArray = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
-
- for (CFIndex i = 0; i < objectCount; ++i) {
- CFTypeRef object = objects[i];
- if (object) {
- CFArrayAppendValue(archiveListArray.get(), object);
- CFRelease(object);
- } else {
- // Append our token null representation.
- CFArrayAppendValue(archiveListArray.get(), tokenNull);
- }
- }
-
- auto dictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-
- auto versionNumber = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &version));
- CFDictionarySetValue(dictionary.get(), CFSTR("version"), versionNumber.get());
- CFDictionarySetValue(dictionary.get(), CFSTR("archiveList"), archiveListArray.get());
-
- if (protocolProperties) {
- CFDictionarySetValue(dictionary.get(), CFSTR("protocolProperties"), protocolProperties);
- CFRelease(protocolProperties);
- }
-
- if (expectedContentLength) {
- CFDictionarySetValue(dictionary.get(), CFSTR("expectedContentLength"), expectedContentLength);
- CFRelease(expectedContentLength);
- }
-
- if (mimeType) {
- CFDictionarySetValue(dictionary.get(), CFSTR("mimeType"), mimeType);
- CFRelease(mimeType);
- }
-
- CFAllocatorDeallocate(kCFAllocatorDefault, objects);
-
- return dictionary;
-}
-
-template<typename ValueType> bool extractDictionaryValue(CFDictionaryRef dictionary, CFStringRef key, ValueType* result)
-{
- auto untypedValue = CFDictionaryGetValue(dictionary, key);
- auto value = dynamic_cf_cast<ValueType>(untypedValue);
- if (untypedValue && !value)
- return false;
- if (result)
- *result = value;
- return true;
-}
-
-static bool createArchiveList(CFDictionaryRef representation, CFTypeRef tokenNull, CFIndex* version, CFTypeRef** objects, CFIndex* objectCount, CFDictionaryRef* protocolProperties, CFNumberRef* expectedContentLength, CFStringRef* mimeType)
-{
- auto versionNumber = dynamic_cf_cast<CFNumberRef>(CFDictionaryGetValue(representation, CFSTR("version")));
- if (!versionNumber)
- return false;
-
- if (!CFNumberGetValue(versionNumber, kCFNumberCFIndexType, version))
- return false;
-
- auto archiveListArray = dynamic_cf_cast<CFArrayRef>(CFDictionaryGetValue(representation, CFSTR("archiveList")));
- if (!archiveListArray)
- return false;
-
- auto archiveListArrayCount = CFArrayGetCount(archiveListArray);
- if (!isInBounds<size_t>(archiveListArrayCount))
- return false;
-
- auto bufferSize = CheckedSize(sizeof(CFTypeRef)) * static_cast<size_t>(archiveListArrayCount);
- if (bufferSize.hasOverflowed())
- return false;
-
- if (!extractDictionaryValue(representation, CFSTR("protocolProperties"), protocolProperties))
- return false;
- if (!extractDictionaryValue(representation, CFSTR("expectedContentLength"), expectedContentLength))
- return false;
- if (!extractDictionaryValue(representation, CFSTR("mimeType"), mimeType))
- return false;
-
- *objectCount = archiveListArrayCount;
- *objects = static_cast<CFTypeRef*>(fastMalloc(bufferSize.unsafeGet()));
-
- CFArrayGetValues(archiveListArray, CFRangeMake(0, *objectCount), *objects);
- for (CFIndex i = 0; i < *objectCount; ++i) {
- if ((*objects)[i] == tokenNull)
- (*objects)[i] = nullptr;
- }
-
- return true;
-}
-
-static RetainPtr<CFDictionaryRef> createSerializableRepresentation(CFURLRequestRef cfRequest, CFTypeRef tokenNull)
-{
- CFIndex version;
- CFTypeRef* objects;
- CFIndex objectCount;
- CFDictionaryRef protocolProperties;
-
- // FIXME (12889518): Do not serialize HTTP message body.
- // 1. It can be large and thus costly to send across.
- // 2. It is misleading to provide a body with some requests, while others use body streams, which cannot be serialized at all.
-
- _CFURLRequestCreateArchiveList(kCFAllocatorDefault, cfRequest, &version, &objects, &objectCount, &protocolProperties);
-
- // This will deallocate the passed in arguments.
- return createSerializableRepresentation(version, objects, objectCount, protocolProperties, nullptr, nullptr, tokenNull);
-}
-
-static RetainPtr<CFURLRequestRef> createCFURLRequestFromSerializableRepresentation(CFDictionaryRef representation, CFTypeRef tokenNull)
-{
- CFIndex version;
- CFTypeRef* objects;
- CFIndex objectCount;
- CFDictionaryRef protocolProperties;
-
- if (!createArchiveList(representation, tokenNull, &version, &objects, &objectCount, &protocolProperties, nullptr, nullptr))
- return nullptr;
-
- auto cfRequest = adoptCF(_CFURLRequestCreateFromArchiveList(kCFAllocatorDefault, version, objects, objectCount, protocolProperties));
- fastFree(objects);
- return WTFMove(cfRequest);
-}
-
-static RetainPtr<CFDictionaryRef> createSerializableRepresentation(NSURLRequest *request, CFTypeRef tokenNull)
-{
- return createSerializableRepresentation([request _CFURLRequest], tokenNull);
-}
-
-static RetainPtr<NSURLRequest> createNSURLRequestFromSerializableRepresentation(CFDictionaryRef representation, CFTypeRef tokenNull)
-{
- auto cfRequest = createCFURLRequestFromSerializableRepresentation(representation, tokenNull);
- if (!cfRequest)
- return nullptr;
-
- return adoptNS([[NSURLRequest alloc] _initWithCFURLRequest:cfRequest.get()]);
-}
-
-void ArgumentCoder<WebCore::ResourceRequest>::encodePlatformData(Encoder& encoder, const WebCore::ResourceRequest& resourceRequest)
-{
- RetainPtr<NSURLRequest> requestToSerialize = resourceRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody);
-
- 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]) {
- requestToSerialize = adoptNS([requestToSerialize mutableCopy]);
- [(NSMutableURLRequest *)requestToSerialize setHTTPBody:nil];
- [(NSMutableURLRequest *)requestToSerialize setHTTPBodyStream:nil];
- }
-
- auto dictionary = createSerializableRepresentation(requestToSerialize.get(), IPC::tokenNullptrTypeRef());
- IPC::encode(encoder, dictionary.get());
-
- WEBCORE_ARGUMENTCODERS_MAC_ENCODE_ADDITIONS
-
- // The fallback array is part of NSURLRequest, but it is not encoded by WKNSURLRequestCreateSerializableRepresentation.
- encoder << resourceRequest.responseContentDispositionEncodingFallbackArray();
- encoder << resourceRequest.requester();
- encoder << resourceRequest.cachePolicy();
- encoder << resourceRequest.isAppBound();
-}
-
-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;
- }
-
- RetainPtr<CFDictionaryRef> dictionary;
- if (!IPC::decode(decoder, dictionary) || !dictionary)
- return false;
-
- auto nsURLRequest = createNSURLRequestFromSerializableRepresentation(dictionary.get(), IPC::tokenNullptrTypeRef());
- if (!nsURLRequest)
- return false;
-
- WEBCORE_ARGUMENTCODERS_MAC_DECODE_ADDITIONS
-
- resourceRequest = WebCore::ResourceRequest(nsURLRequest.get());
-
- Vector<String> responseContentDispositionEncodingFallbackArray;
- if (!decoder.decode(responseContentDispositionEncodingFallbackArray))
- return false;
-
- resourceRequest.setResponseContentDispositionEncodingFallbackArray(
- responseContentDispositionEncodingFallbackArray.size() > 0 ? responseContentDispositionEncodingFallbackArray[0] : String(),
- responseContentDispositionEncodingFallbackArray.size() > 1 ? responseContentDispositionEncodingFallbackArray[1] : String(),
- responseContentDispositionEncodingFallbackArray.size() > 2 ? responseContentDispositionEncodingFallbackArray[2] : String()
- );
-
- WebCore::ResourceRequest::Requester requester;
- if (!decoder.decode(requester))
- return false;
- resourceRequest.setRequester(requester);
-
- WebCore::ResourceRequestCachePolicy cachePolicy;
- if (!decoder.decode(cachePolicy))
- return false;
- resourceRequest.setCachePolicy(cachePolicy);
-
- bool isAppBound;
- if (!decoder.decode(isAppBound))
- return false;
- resourceRequest.setIsAppBound(isAppBound);
-
- return true;
-}
-
void ArgumentCoder<WebCore::CertificateInfo>::encode(Encoder& encoder, const WebCore::CertificateInfo& certificateInfo)
{
encoder << certificateInfo.type();