RESOLVED FIXED Bug 222145
Serialize NSURLRequest (rather than CFURLRequest) in IPC
https://bugs.webkit.org/show_bug.cgi?id=222145
Summary Serialize NSURLRequest (rather than CFURLRequest) in IPC
Brent Fulgham
Reported 2021-02-18 17:07:04 PST
When building on modern Cocoa platforms we should serialize the actual NSURLRequest, rather than bridging to CFURLRequest and serializing that. This allows us to send more state across IPC (since CFURLRequest has been largely unchanged in the past 5+ years and does not reflect all of the features of NSURLRequest).
Attachments
Patch (4.17 KB, patch)
2021-02-18 17:11 PST, Brent Fulgham
no flags
More complete change. (20.54 KB, patch)
2021-02-19 12:54 PST, Brent Fulgham
no flags
Rebaselined (20.63 KB, patch)
2021-02-19 13:12 PST, Brent Fulgham
ews-feeder: commit-queue-
Another try. (20.62 KB, patch)
2021-02-19 13:21 PST, Brent Fulgham
ews-feeder: commit-queue-
Yet another try (20.62 KB, patch)
2021-02-19 13:30 PST, Brent Fulgham
no flags
Patch (18.25 KB, patch)
2021-02-19 15:11 PST, Brent Fulgham
ews-feeder: commit-queue-
WIP: Trying to locate test failure. (16.38 KB, patch)
2021-02-19 21:03 PST, Brent Fulgham
no flags
WIP: Trying to locate test failure. (18.98 KB, patch)
2021-02-19 21:21 PST, Brent Fulgham
no flags
Logging to identify serialization error. (21.67 KB, patch)
2021-02-20 13:46 PST, Brent Fulgham
no flags
Additional logging (25.15 KB, patch)
2021-02-20 16:14 PST, Brent Fulgham
no flags
Now switch serializer and log (27.03 KB, patch)
2021-02-20 17:49 PST, Brent Fulgham
no flags
Patch (24.01 KB, patch)
2021-02-23 12:06 PST, Brent Fulgham
no flags
Patch (30.58 KB, patch)
2021-02-24 09:50 PST, Brent Fulgham
no flags
Patch (30.55 KB, patch)
2021-02-24 11:16 PST, Brent Fulgham
no flags
Patch (32.74 KB, patch)
2021-02-24 14:21 PST, Brent Fulgham
no flags
Patch (33.06 KB, patch)
2021-02-24 15:23 PST, Brent Fulgham
no flags
Patch (27.80 KB, patch)
2021-02-24 17:26 PST, Brent Fulgham
no flags
Patch for landing (31.09 KB, patch)
2021-02-25 12:11 PST, Brent Fulgham
no flags
Patch to address Blob test (22.09 KB, patch)
2021-02-25 18:23 PST, Brent Fulgham
no flags
Radar WebKit Bug Importer
Comment 1 2021-02-18 17:07:21 PST
Brent Fulgham
Comment 2 2021-02-18 17:11:35 PST
Brent Fulgham
Comment 3 2021-02-18 17:19:15 PST
I believe this patch could be extended a bit, since Cache Policy seems to be brought over with the NSURLRequest NSData object. We might be able to skip manually serializing responseContentDispositionEncodingFallbackArray as well. It looks like 'requester' is not serialized through NSURLRequest (it's probably a WebKit concept).
Darin Adler
Comment 4 2021-02-18 19:12:25 PST
Comment on attachment 420888 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=420888&action=review Looks OK but I think we can do better. > Source/WebKit/ChangeLog:16 > + * Shared/mac/WebCoreArgumentCodersMac.mm: Shouldn't this be in the Cocoa.mm file, not the Mac.mm file? I assume we use it on iOS, not just Mac. > Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:219 > + NSError *error = nil; > + auto *archivedData = [NSKeyedArchiver archivedDataWithRootObject:requestToSerialize.get() requiringSecureCoding:YES error:&error]; > + if (error) > + LOG_ERROR("Failed to encode NSURLRequest: %d", error.code); > + IPC::encode(encoder, (__bridge CFDataRef)archivedData); This should use WebCoreArgumentCodersCocoa.h. I believe it can just be this: encode(encoder, requestToSerialize.get()); > Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:223 > encoder << resourceRequest.responseContentDispositionEncodingFallbackArray(); Is this still correct with NSURLRequest serialization? > Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:257 > + RetainPtr<CFDataRef> data; > + if (!IPC::decode(decoder, data) || !data) > + return false; > + > + NSError *error = nil; > + auto nsURLRequest = retainPtr([NSKeyedUnarchiver unarchivedObjectOfClass:[NSURLRequest class] fromData:(__bridge NSData *)data.get() error:&error]); > + if (error) { > + LOG_ERROR("Failed to decode NSURLRequest: %d", error.code); > + return false; > + } This would just be: auto request = decode(decoder, NSURLRequest.class); if (!request) return false;
Brent Fulgham
Comment 5 2021-02-18 19:27:28 PST
Comment on attachment 420888 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=420888&action=review Thanks for reviewing. I’m going to investigate the api-Mac failure in case it’s related, and see if I can move this implementation to the Cocoa file. >> Source/WebKit/ChangeLog:16 >> + * Shared/mac/WebCoreArgumentCodersMac.mm: > > Shouldn't this be in the Cocoa.mm file, not the Mac.mm file? I assume we use it on iOS, not just Mac. It should! It caused me a lot of confusion initially, but I didn’t want to move too many things in one patch. Maybe I could do a separate change for that. >> Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:223 >> encoder << resourceRequest.responseContentDispositionEncodingFallbackArray(); > > Is this still correct with NSURLRequest serialization? I don’t think so — I think only “requester” needs to be serialized after this change.
Alex Christensen
Comment 6 2021-02-19 08:26:59 PST
Comment on attachment 420888 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=420888&action=review > Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:53 > +#if USE(CFURLCONNECTION) I think we should just remove this code. USE(CFURLCONNECTION) is only true on the AppleWin port, which doesn't support WebKit2.
Brent Fulgham
Comment 7 2021-02-19 12:08:19 PST
Comment on attachment 420888 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=420888&action=review >>> Source/WebKit/ChangeLog:16 >>> + * Shared/mac/WebCoreArgumentCodersMac.mm: >> >> Shouldn't this be in the Cocoa.mm file, not the Mac.mm file? I assume we use it on iOS, not just Mac. > > It should! It caused me a lot of confusion initially, but I didn’t want to move too many things in one patch. Maybe I could do a separate change for that. Actually, I think moving the NSURLRequest version (and leaving the old CFURLRequest version) makes sense. >> Source/WebKit/Shared/mac/WebCoreArgumentCodersMac.mm:257 >> + } > > This would just be: > > auto request = decode(decoder, NSURLRequest.class); > if (!request) > return false; Nice!
Darin Adler
Comment 8 2021-02-19 12:11:08 PST
Comment on attachment 420888 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=420888&action=review >>>> Source/WebKit/ChangeLog:16 >>>> + * Shared/mac/WebCoreArgumentCodersMac.mm: >>> >>> Shouldn't this be in the Cocoa.mm file, not the Mac.mm file? I assume we use it on iOS, not just Mac. >> >> It should! It caused me a lot of confusion initially, but I didn’t want to move too many things in one patch. Maybe I could do a separate change for that. > > Actually, I think moving the NSURLRequest version (and leaving the old CFURLRequest version) makes sense. See Alex’s comments that make it clear we can remove the old CFURLRequest version entirely.
Brent Fulgham
Comment 9 2021-02-19 12:54:30 PST
Created attachment 421017 [details] More complete change.
Brent Fulgham
Comment 10 2021-02-19 13:12:43 PST
Created attachment 421020 [details] Rebaselined
Brent Fulgham
Comment 11 2021-02-19 13:21:18 PST
Created attachment 421026 [details] Another try.
Brent Fulgham
Comment 12 2021-02-19 13:30:44 PST
Created attachment 421027 [details] Yet another try
Alex Christensen
Comment 13 2021-02-19 13:54:52 PST
Comment on attachment 421027 [details] Yet another try View in context: https://bugs.webkit.org/attachment.cgi?id=421027&action=review > Tools/ChangeLog:10 > + and to test the updated IPC serialization for NSURLRequest.:q :q > Tools/TestWebKitAPI/Tests/WebKitCocoa/LoadInvalidURLRequest.mm:96 > + EXPECT_WK_STREQ([error.userInfo[@"NSErrorFailingURLKey"] absoluteString], "http://%E2%80%80"); Note: this test verifies that nothing crashes during this. The expectation changed surprisingly in https://bugs.webkit.org/show_bug.cgi?id=214314 and this is changing it back, which is probably a good thing. Important are the facts that this doesn't crash and the URLExtras_ParsingError API test doesn't change expectations.
Brent Fulgham
Comment 14 2021-02-19 14:05:03 PST
(In reply to Alex Christensen from comment #13) > Comment on attachment 421027 [details] > Yet another try > > View in context: > https://bugs.webkit.org/attachment.cgi?id=421027&action=review > > > Tools/ChangeLog:10 > > + and to test the updated IPC serialization for NSURLRequest.:q > > :q vi!!!! > > > Tools/TestWebKitAPI/Tests/WebKitCocoa/LoadInvalidURLRequest.mm:96 > > + EXPECT_WK_STREQ([error.userInfo[@"NSErrorFailingURLKey"] absoluteString], "http://%E2%80%80"); > > Note: this test verifies that nothing crashes during this. The expectation > changed surprisingly in https://bugs.webkit.org/show_bug.cgi?id=214314 and > this is changing it back, which is probably a good thing. Important are the > facts that this doesn't crash and the URLExtras_ParsingError API test > doesn't change expectations.
Brent Fulgham
Comment 15 2021-02-19 15:11:44 PST
Alex Christensen
Comment 16 2021-02-19 17:20:49 PST
Comment on attachment 421042 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421042&action=review I'm assuming you've verified that NSURLRequest does encode responseContentDispositionEncodingFallbackArray, cachePolicy, protocolProperties, expectedContentLength, version, archiveList, and mimeType where CFURLRequest does not. > Tools/ChangeLog:10 > + and to test the updated IPC serialization for NSURLRequest.:q :q
Brent Fulgham
Comment 17 2021-02-19 17:37:37 PST
Comment on attachment 421042 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421042&action=review >> Tools/ChangeLog:10 >> + and to test the updated IPC serialization for NSURLRequest.:q > > :q !!
Brent Fulgham
Comment 18 2021-02-19 17:41:04 PST
(In reply to Alex Christensen from comment #16) > Comment on attachment 421042 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=421042&action=review > > I'm assuming you've verified that NSURLRequest does encode > responseContentDispositionEncodingFallbackArray, cachePolicy, > protocolProperties, expectedContentLength, version, archiveList, and > mimeType where CFURLRequest does not. It looks like we definitely do pick up the responseContentDispositionEncodingFallbackArray, cachePolicy, protocolProperties, and version, but I can't find evidence that expectedContentLength and mimeType are picked up. (archiveList is just a detail of our serialization work). I'll side-serialize expectedContentLength and mimeType.
Brent Fulgham
Comment 19 2021-02-19 17:44:13 PST
(In reply to Brent Fulgham from comment #18) > (In reply to Alex Christensen from comment #16) > > Comment on attachment 421042 [details] > > Patch > > > > View in context: > > https://bugs.webkit.org/attachment.cgi?id=421042&action=review > > > > I'm assuming you've verified that NSURLRequest does encode > > responseContentDispositionEncodingFallbackArray, cachePolicy, > > protocolProperties, expectedContentLength, version, archiveList, and > > mimeType where CFURLRequest does not. > > It looks like we definitely do pick up the > responseContentDispositionEncodingFallbackArray, cachePolicy, > protocolProperties, and version, but I can't find evidence that > expectedContentLength and mimeType are picked up. (archiveList is just a > detail of our serialization work). > > I'll side-serialize expectedContentLength and mimeType. Wait -- no. Those are for NSURLResponse, and were only in that method because it was shared for NSURLResponse serialization.
Darin Adler
Comment 20 2021-02-19 18:17:30 PST
Comment on attachment 421042 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421042&action=review > Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:549 > + RetainPtr<NSURLRequest> requestToSerialize = resourceRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody); I suggest this style: auto requestToSerialize = retainPtr(xxx); > Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:562 > + requestToSerialize = adoptNS([requestToSerialize mutableCopy]); > + [(NSMutableURLRequest *)requestToSerialize setHTTPBody:nil]; > + [(NSMutableURLRequest *)requestToSerialize setHTTPBodyStream:nil]; I’d write: auto mutableRequest = adoptNS([requestToSerialize mutableCopy]); [mutableRequest setHTTPBody:nil]; [mutableRequest setHTTPBodyStream:nil]; requestToSerialize = WTFMove(mutableRequest); > Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:586 > + resourceRequest = WebCore::ResourceRequest(request->get()); I would move this down after the last return false. > Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:591 > + resourceRequest.setRequester(requester); I would move this down after the last return false.
Brent Fulgham
Comment 21 2021-02-19 19:55:29 PST
Comment on attachment 421042 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421042&action=review >> Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:549 >> + RetainPtr<NSURLRequest> requestToSerialize = resourceRequest.nsURLRequest(WebCore::HTTPBodyUpdatePolicy::DoNotUpdateHTTPBody); > > I suggest this style: > > auto requestToSerialize = retainPtr(xxx); Will do. I also see some ITP-related errors, so I'm going to do a bit more validation of the serialization to make sure we weren't relying on some idiosyncrasy of the CFURLRequest before landing. I'll be sure to adopt these suggestions, too. >> Source/WebKit/Shared/Cocoa/WebCoreArgumentCodersCocoa.mm:562 >> + [(NSMutableURLRequest *)requestToSerialize setHTTPBodyStream:nil]; > > I’d write: > > auto mutableRequest = adoptNS([requestToSerialize mutableCopy]); > [mutableRequest setHTTPBody:nil]; > [mutableRequest setHTTPBodyStream:nil]; > requestToSerialize = WTFMove(mutableRequest); Will do.
Brent Fulgham
Comment 22 2021-02-19 21:03:49 PST
Created attachment 421077 [details] WIP: Trying to locate test failure.
Brent Fulgham
Comment 23 2021-02-19 21:06:42 PST
(In reply to Brent Fulgham from comment #22) > Created attachment 421077 [details] > WIP: Trying to locate test failure. I added some assertions to try to understand why the ITP tests would fail with this change.
Brent Fulgham
Comment 24 2021-02-19 21:21:12 PST
Created attachment 421079 [details] WIP: Trying to locate test failure.
Brent Fulgham
Comment 25 2021-02-20 13:46:55 PST
Created attachment 421108 [details] Logging to identify serialization error.
Brent Fulgham
Comment 26 2021-02-20 16:14:26 PST
Created attachment 421119 [details] Additional logging
Brent Fulgham
Comment 27 2021-02-20 17:49:39 PST
Created attachment 421122 [details] Now switch serializer and log
Brent Fulgham
Comment 28 2021-02-23 12:06:02 PST
Darin Adler
Comment 29 2021-02-23 12:37:11 PST
Comment on attachment 421338 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421338&action=review > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:115 > + _URL = [[NSURL _URLWithData:[NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO] relativeToURL:nil] retain]; WebCore uses CFURLCreateAbsoluteURLWithBytes. Why is it important to use something different here?
David Kilzer (:ddkilzer)
Comment 30 2021-02-23 12:44:22 PST
Comment on attachment 421338 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421338&action=review r- to fix leaks. Nits are optional. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:58 > +@interface NSURL (NSURLExtrasInternal) > ++ (NSURL *)_URLWithData:(NSData *)data relativeToURL:(NSURL *)baseURL; > @end Nit: Should this be declared in an SPI.h header instead of here? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:63 > +@interface WKEncodedURL : NSObject <NSSecureCoding> > +- (instancetype)initWithURL:(NSURL *)url; > +@property (nonatomic, readonly) NSURL *URL; > +@end Nit: Why use `url` for one variable but `URL` in the other? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:70 > if ([object isKindOfClass:[NSFont class]]) { Nit: Could use dynamic_objc_cast<NSFont>() here. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:78 > + if ([object isKindOfClass:[NSURL class]]) Nit: Could use dynamic_objc_cast<NSURL>() here. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:82 > + return [[WKEncodedURL alloc] initWithURL:object]; > + > + return object; > +} Does this method return a +1 retained object or an (autoreleased/non-retained) object? If it's meant to return a +1 retained object (probably not based on the method signature—check if the protocol has NS_RETURNS_RETAINED on the definition), then you're under-retaining `object` when returning it here. If it's meant to return an autoreleased/non-retained object, then you're leaking the WKEncodedURLhere, which should have -autorelease called on it instead to fix the bug. You probably need to call -autorelease on the WKEncodedURL object (or do the equivalent RetainPtr<> thing if you store the object in a RetainPtr<> via adoptNS()). > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:86 > + if ([object isKindOfClass:[WKEncodedURL class]]) Nit: Could use dynamic_objc_cast<WKEncodedURL>() here. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:113 > + auto bytes = (uint8_t *)[coder decodeBytesWithReturnedLength:&length]; > + if (!bytes) > + return nil; You ned to release `self` here in the early return, otherwise it will leak. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:117 > + _URL = [[NSURL _URLWithData:[NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO] relativeToURL:nil] retain]; > + if (!_URL) > + return nil; Ditto. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:130 > +@end You are missing a -dealloc method here to release the `_URL` instance variable, so `_URL` will leak when the WKEncodedURL is released. (If you do this, don't forget the call to `[super dealloc]` at the end of the method.) Could also solve this by using a RetainPtr<WKEncodedURL> for the instance variable, along with other syntax changes needed for that, then -dealloc is not needed. > Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewLoadAPIs.mm:157 > + [[NSFileManager defaultManager] removeItemAtURL:testFile error:nil]; > + [[NSFileManager defaultManager] removeItemAtURL:testDirectory error:nil]; Nit: Could pull out `[NSFileManager defaultManager]` into a local variable to save 5 extra Objective-C method calls.
Brent Fulgham
Comment 31 2021-02-24 09:50:58 PST
David Kilzer (:ddkilzer)
Comment 32 2021-02-24 10:31:27 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review r=me (no changes required). Leaving r? since I assume you want another review. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:64 > -- (id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object > +- (id _Nullable)archiver:(NSKeyedArchiver *_Nonnull)archiver willEncodeObject:(id _Nonnull)object Nit: Does this method signature still match the NSKeyedArchiverDelegate protocol method? No, it doesn't match exactly (via <Foundation/NSKeyedArchiver.h>): - (nullable id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object; However, it's probably okay if the method signature doesn't match exactly since nullability hints are for the compiler, and the ObjC runtime doesn't care as long as the rest of the signature matches. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:80 > +- (id _Nullable)unarchiver:(NSKeyedUnarchiver * _Nonnull)unarchiver didDecodeObject:(id _Nullable) NS_RELEASES_ARGUMENT object NS_RETURNS_RETAINED Good catch matching the NSKeyedUnarchiverDelegate protocol definition! > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:84 > + [encodedURL release]; Nit: The clang static analyzer may be able to reason about this method better if you used this instead: [object release]; In practice, it doesn't matter whether you use `object` or `encodedURL`, though.
Geoffrey Garen
Comment 33 2021-02-24 10:35:48 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:75 > + return [[[WKEncodedURL alloc] initWithURL:url] autorelease]; I think Chris Dumez would suggest you do adoptNS([[[WKEncodedURL alloc] initWithURL:url]).autorelease() instead. Otherwise, this is tiny step backwards in smart pointer adoption. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:86 > + if (auto *encodedURL = dynamic_objc_cast<WKEncodedURL>(object)) { > + auto url = retainPtr(encodedURL.url); > + [encodedURL release]; > + return url.leakRef(); > + } Manual -release is a tiny step backwards in smart pointer adoption. I'd suggest: auto objectPtr = adoptNS(object); if (auto *encodedURL = dynamic_objc_cast<WKEncodedURL>(objectPtr.get())) return retainPtr(encodedURL.url).leakRef(); return objectPtr.leakRef(); > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:116 > + if (self = [super init]) { Let's put self in a RetainPtr to remove manual release.
Brent Fulgham
Comment 34 2021-02-24 11:05:16 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:64 >> +- (id _Nullable)archiver:(NSKeyedArchiver *_Nonnull)archiver willEncodeObject:(id _Nonnull)object > > Nit: Does this method signature still match the NSKeyedArchiverDelegate protocol method? No, it doesn't match exactly (via <Foundation/NSKeyedArchiver.h>): > > - (nullable id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object; > > However, it's probably okay if the method signature doesn't match exactly since nullability hints are for the compiler, and the ObjC runtime doesn't care as long as the rest of the signature matches. The compiler complained about nullability declarations until I got it to this point. I'm not sure why it's happy with the NSKeyedArchiver.h version and not this one. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:75 >> + return [[[WKEncodedURL alloc] initWithURL:url] autorelease]; > > I think Chris Dumez would suggest you do adoptNS([[[WKEncodedURL alloc] initWithURL:url]).autorelease() instead. Otherwise, this is tiny step backwards in smart pointer adoption. Oh! Will fix. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:80 >> +- (id _Nullable)unarchiver:(NSKeyedUnarchiver * _Nonnull)unarchiver didDecodeObject:(id _Nullable) NS_RELEASES_ARGUMENT object NS_RETURNS_RETAINED > > Good catch matching the NSKeyedUnarchiverDelegate protocol definition! I'm learning! >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:84 >> + [encodedURL release]; > > Nit: The clang static analyzer may be able to reason about this method better if you used this instead: > > [object release]; > > In practice, it doesn't matter whether you use `object` or `encodedURL`, though. I'll use 'object' to help the analyzer. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:86 >> + } > > Manual -release is a tiny step backwards in smart pointer adoption. > > I'd suggest: > > auto objectPtr = adoptNS(object); > if (auto *encodedURL = dynamic_objc_cast<WKEncodedURL>(objectPtr.get())) > return retainPtr(encodedURL.url).leakRef(); > > return objectPtr.leakRef(); Will do. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:116 >> + if (self = [super init]) { > > Let's put self in a RetainPtr to remove manual release. Will do.
Brent Fulgham
Comment 35 2021-02-24 11:16:20 PST
Darin Adler
Comment 36 2021-02-24 11:23:13 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review >>> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:64 >>> +- (id _Nullable)archiver:(NSKeyedArchiver *_Nonnull)archiver willEncodeObject:(id _Nonnull)object >> >> Nit: Does this method signature still match the NSKeyedArchiverDelegate protocol method? No, it doesn't match exactly (via <Foundation/NSKeyedArchiver.h>): >> >> - (nullable id)archiver:(NSKeyedArchiver *)archiver willEncodeObject:(id)object; >> >> However, it's probably okay if the method signature doesn't match exactly since nullability hints are for the compiler, and the ObjC runtime doesn't care as long as the rest of the signature matches. > > The compiler complained about nullability declarations until I got it to this point. I'm not sure why it's happy with the NSKeyedArchiver.h version and not this one. The one in NSKeyedArchiver.h is written differently because it's inside a NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END pair, but it means the same as what’s written above. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:111 > + WTF::URLCharBuffer urlBytes; > + WTF::getURLBytes((__bridge CFURLRef)m_url.get(), urlBytes); > + [coder encodeBytes:urlBytes.data() length:urlBytes.size()]; This doesn’t handle the case where m_url is null; seems strange to go out of our way always to say it’s nullable but then not handle the null value. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:124 > + m_url = retainPtr(WTF::URLWithData([NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO], nil)); Should not need to write retainPtr here. Assigning into a RetainPtr should work without that. I think we should avoid creating and autoreleasing an NSData object here by making a function like URLWithData that takes a pointer and a length; it would be very easy to refactor that function to work without an object. Could do that as a follow-up refactor to improve efficiency; doesn’t seem necessary to do it in the first cut.
Brent Fulgham
Comment 37 2021-02-24 14:21:51 PST
Brent Fulgham
Comment 38 2021-02-24 14:36:34 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:111 >> + [coder encodeBytes:urlBytes.data() length:urlBytes.size()]; > > This doesn’t handle the case where m_url is null; seems strange to go out of our way always to say it’s nullable but then not handle the null value. Ah! Okay -- I will address that. I uploaded another patch before I saw these comments, so I will upload another patch soon.
Brent Fulgham
Comment 39 2021-02-24 15:15:44 PST
Comment on attachment 421417 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421417&action=review >>> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:111 >>> + [coder encodeBytes:urlBytes.data() length:urlBytes.size()]; >> >> This doesn’t handle the case where m_url is null; seems strange to go out of our way always to say it’s nullable but then not handle the null value. > > Ah! Okay -- I will address that. I uploaded another patch before I saw these comments, so I will upload another patch soon. Actually, after playing with this a bit I think we should mark the URL as _Nonnull. The serialization doesn't expect to encounter null URLs (we always serialize an empty string URL), and the result of this serialization is passed to CFURL functions that do not expect a null URL.
Darin Adler
Comment 40 2021-02-24 15:20:41 PST
(In reply to Brent Fulgham from comment #39) > Actually, after playing with this a bit I think we should mark the URL as > _Nonnull. The serialization doesn't expect to encounter null URLs (we always > serialize an empty string URL), and the result of this serialization is > passed to CFURL functions that do not expect a null URL. Excellent.
Brent Fulgham
Comment 41 2021-02-24 15:23:30 PST
Darin Adler
Comment 42 2021-02-24 16:04:10 PST
Comment on attachment 421470 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421470&action=review Looks good. I still have style comments (all optional, but most are good ideas), and one comment that *might* be a correctness issue, the return value of initWithCoder: when decoding fails. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:58 > +- (instancetype _Nullable)initWithURL:(NSURL *_Nonnull)url; On reflection after reading multiple iterations of this patch, it seems to me we want to wrap the contents of this file into NS_ASSUME_NONNULL_BEGIN/END. We then would only have to annotate nullable things rather than also having to annotate all the non-null things. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:59 > +@property (nonatomic, readonly) NSURL *_Nonnull url; Could avoid the lowercase url by naming this wrappedURL (or targetURL, or underlyingURL). > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:67 > + if (auto *font = dynamic_objc_cast<NSFont>(object)) { I slightly prefer: if (auto font = xxx Maybe we could debate the merits? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:74 > + if (auto *url = dynamic_objc_cast<NSURL>(object)) Ditto. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:82 > + auto objectPtr = adoptNS(object); Not sure objectPtr is a great name. After all "object" is already a pointer. Maybe adoptedObject? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:83 > + if (auto *encodedURL = dynamic_objc_cast<WKEncodedURL>(objectPtr.get())) Same comment about auto. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:91 > +@implementation WKEncodedURL { I don’t think "encoded URL" is a great name for this. The URL in this object is not "encoded". This is a proxy that facilitates encoding and decoding the URL. It does in fact function as the "decoded URL" in the decoding process, but during the encoding process it is not at all the "encoded" URL. I would name this class something like "WKURLArchivalWrapper" or "WKSecureCodingURLWrapper". > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:92 > + RetainPtr<NSURL> m_url; Could avoid the lowercase url by naming this m_wrappedURL (or m_targetURL or m_underlyingURL). > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:125 > + m_url = retainPtr([NSURL URLWithString:@""]); Should not need to call retainPtr here. But also shouldn’t we return nil here, letting self get released, instead of setting the URL to ""? We want to correctly indicate failure rather than emptying out the URL and incorrectly indicating success. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:196 > +static inline bool isSerializableFont(CTFontRef _Nullable font) What determines where we use "nullable" and where we use "_Nullable"? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:441 > + auto allowedClassSet = [NSMutableSet setWithArray:allowedClasses]; Could remove one autorelease by doing this instead: auto allowedClassSet = adoptNS([[NSMutableSet alloc] initWithArray:allowedClasses]);
Brent Fulgham
Comment 43 2021-02-24 17:22:34 PST
Comment on attachment 421470 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421470&action=review Thanks for the review! >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:58 >> +- (instancetype _Nullable)initWithURL:(NSURL *_Nonnull)url; > > On reflection after reading multiple iterations of this patch, it seems to me we want to wrap the contents of this file into NS_ASSUME_NONNULL_BEGIN/END. We then would only have to annotate nullable things rather than also having to annotate all the non-null things. It definitely makes the patch smaller -- I'll do so. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:67 >> + if (auto *font = dynamic_objc_cast<NSFont>(object)) { > > I slightly prefer: > > if (auto font = xxx > > Maybe we could debate the merits? No objections! >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:82 >> + auto objectPtr = adoptNS(object); > > Not sure objectPtr is a great name. After all "object" is already a pointer. Maybe adoptedObject? Will do. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:83 >> + if (auto *encodedURL = dynamic_objc_cast<WKEncodedURL>(objectPtr.get())) > > Same comment about auto. Done. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:91 >> +@implementation WKEncodedURL { > > I don’t think "encoded URL" is a great name for this. The URL in this object is not "encoded". This is a proxy that facilitates encoding and decoding the URL. It does in fact function as the "decoded URL" in the decoding process, but during the encoding process it is not at all the "encoded" URL. > > I would name this class something like "WKURLArchivalWrapper" or "WKSecureCodingURLWrapper". I'll use WKSecureCodingURLWrapper. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:92 >> + RetainPtr<NSURL> m_url; > > Could avoid the lowercase url by naming this m_wrappedURL (or m_targetURL or m_underlyingURL). Done. m_wrappedURL. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:125 >> + m_url = retainPtr([NSURL URLWithString:@""]); > > Should not need to call retainPtr here. > > But also shouldn’t we return nil here, letting self get released, instead of setting the URL to ""? We want to correctly indicate failure rather than emptying out the URL and incorrectly indicating success. Good point. I'll do that. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:134 > + m_url = retainPtr(url); Based on your other comments it occurs to me that I shouldn't do a retainPtr() here. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:196 >> +static inline bool isSerializableFont(CTFontRef _Nullable font) > > What determines where we use "nullable" and where we use "_Nullable"? I based it on what the compiler accepted. It seems like "nullable" is allowed in property declarations, but function signatures need _Nullable. But I might be mistaken. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:441 >> + auto allowedClassSet = [NSMutableSet setWithArray:allowedClasses]; > > Could remove one autorelease by doing this instead: > > auto allowedClassSet = adoptNS([[NSMutableSet alloc] initWithArray:allowedClasses]); Oh! Good catch.
Brent Fulgham
Comment 44 2021-02-24 17:26:34 PST
Brent Fulgham
Comment 45 2021-02-24 17:28:05 PST
(In reply to Darin Adler from comment #42) > Comment on attachment 421470 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=421470&action=review > > Looks good. I still have style comments (all optional, but most are good > ideas), and one comment that *might* be a correctness issue, the return > value of initWithCoder: when decoding fails. Just to complicate things, I took another look at how CFURL had been serialized, and tried to more closely follow that model (and how it's done in Foundation). I now think that this accurately models how URL's are serialized both in WebKit, and in Foundation, and should now be correct. Let's see whether the bots find anything.
Darin Adler
Comment 46 2021-02-24 17:54:09 PST
Comment on attachment 421486 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421486&action=review > Source/WTF/wtf/cocoa/NSURLExtras.mm:169 > + // So only return early if the character after the slash is somethihg else. Typo in the word "something" here. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:60 > +- (instancetype _Nullable)initWithURL:(NSURL *)url; Could use the wrappedURL name here too, to make it look nicer. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:76 > + if (auto url = dynamic_objc_cast<NSURL>(object)) Could use the wrappedURL name here too, to make it look nicer. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:107 > +NSString * const baseURLExistsKey = @"WK.baseURLExists"; This is not used in the code below. If this was marked static, you would have gotten a compiler warning about it being unused. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:108 > +NSString * const baseURLKey = @"WK.baseURL"; Since this is limited to the file it should have static. Could use constexpr for this. The syntax is nicer: static constexpr NSString *baseURLKey = @"WK.baseURL"; Might also not even need "static" with constexpr, but I think it’s correct to do both. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:128 > + auto selfPtr = adoptNS([super init]); > + if (selfPtr) { Can just write this instead of nesting the entire function: auto selfPtr = adoptNS([super init]); if (!selfPtr) return nil; > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:134 > + baseURL = (NSURL *)[coder decodeObjectOfClass:NSURL.class forKey:baseURLKey]; Does this end up recursively using this method? > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:472 > [unarchiver finishDecoding]; > + unarchiver.get().delegate = nil; Does this code *actually* run before the function returns even though we have return inside the @try and @catch?
Brent Fulgham
Comment 47 2021-02-25 09:32:59 PST
Comment on attachment 421486 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421486&action=review >> Source/WTF/wtf/cocoa/NSURLExtras.mm:169 >> + // So only return early if the character after the slash is somethihg else. > > Typo in the word "something" here. Doh! >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:60 >> +- (instancetype _Nullable)initWithURL:(NSURL *)url; > > Could use the wrappedURL name here too, to make it look nicer. Will do. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:76 >> + if (auto url = dynamic_objc_cast<NSURL>(object)) > > Could use the wrappedURL name here too, to make it look nicer. Good idea. And I should use "wrapper" instead of "encodedURL" below. > Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:86 > + return retainPtr(encodedURL.wrappedURL).leakRef(); ... so this becomes "wrapper.wrappedURL", which is more precise. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:107 >> +NSString * const baseURLExistsKey = @"WK.baseURLExists"; > > This is not used in the code below. If this was marked static, you would have gotten a compiler warning about it being unused. Oh! yes, I thought I would need to use this but didn't. I'll remove it. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:108 >> +NSString * const baseURLKey = @"WK.baseURL"; > > Since this is limited to the file it should have static. Could use constexpr for this. The syntax is nicer: > > static constexpr NSString *baseURLKey = @"WK.baseURL"; > > Might also not even need "static" with constexpr, but I think it’s correct to do both. Will do. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:128 >> + if (selfPtr) { > > Can just write this instead of nesting the entire function: > > auto selfPtr = adoptNS([super init]); > if (!selfPtr) > return nil; Will do. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:134 >> + baseURL = (NSURL *)[coder decodeObjectOfClass:NSURL.class forKey:baseURLKey]; > > Does this end up recursively using this method? This is the algorithm used by Foundation to serialize these objects, so I believe it is correct. I will add another TestWebKitAPI test that confirms we terminate. >> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:472 >> + unarchiver.get().delegate = nil; > > Does this code *actually* run before the function returns even though we have return inside the @try and @catch? Yes -- I confirmed this in the debugger before putting it here. I originally set the delegate to nil in the @try and @catch blocks, but found that serialization failed because 'finishDecoding' was unsuccessful without the delegate (which had been cleared before reaching @finally).
Darin Adler
Comment 48 2021-02-25 10:33:19 PST
Comment on attachment 421486 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=421486&action=review >>> Source/WebKit/Shared/Cocoa/ArgumentCodersCocoa.mm:134 >>> + baseURL = (NSURL *)[coder decodeObjectOfClass:NSURL.class forKey:baseURLKey]; >> >> Does this end up recursively using this method? > > This is the algorithm used by Foundation to serialize these objects, so I believe it is correct. I will add another TestWebKitAPI test that confirms we terminate. Sure, and looks good, but want to make sure that it does correctly end up using this function. I don’t think it will infinitely recurse because eventually we will have a URL without a base.
Brent Fulgham
Comment 49 2021-02-25 12:11:27 PST
Created attachment 421553 [details] Patch for landing
EWS
Comment 50 2021-02-25 12:40:50 PST
Committed r273503: <https://commits.webkit.org/r273503> All reviewed patches have been landed. Closing bug and clearing flags on attachment 421553 [details].
WebKit Commit Bot
Comment 51 2021-02-25 15:50:39 PST
Re-opened since this is blocked by bug 222442
Brent Fulgham
Comment 52 2021-02-25 18:23:13 PST
Created attachment 421592 [details] Patch to address Blob test
Brent Fulgham
Comment 53 2021-02-25 18:24:38 PST
Comment on attachment 421592 [details] Patch to address Blob test Sadly, WTF::URLFromBytes() doesn't handle URL fragments (e.g., "/action" from a Form) properly, so I'm switching to the behavior of ArgumentCodersCF (which I should have done from the beginning). If EWS is green across all tests, I'll land.
EWS
Comment 54 2021-02-25 21:06:51 PST
Committed r273541: <https://commits.webkit.org/r273541> All reviewed patches have been landed. Closing bug and clearing flags on attachment 421592 [details].
Note You need to log in before you can comment on or make changes to this bug.