Bug 222145 - Serialize NSURLRequest (rather than CFURLRequest) in IPC
Summary: Serialize NSURLRequest (rather than CFURLRequest) in IPC
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Misc. (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Brent Fulgham
URL:
Keywords: InRadar
Depends on: 222242 222442
Blocks: 222441
  Show dependency treegraph
 
Reported: 2021-02-18 17:07 PST by Brent Fulgham
Modified: 2021-04-08 13:35 PDT (History)
13 users (show)

See Also:


Attachments
Patch (4.17 KB, patch)
2021-02-18 17:11 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
More complete change. (20.54 KB, patch)
2021-02-19 12:54 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Rebaselined (20.63 KB, patch)
2021-02-19 13:12 PST, Brent Fulgham
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Another try. (20.62 KB, patch)
2021-02-19 13:21 PST, Brent Fulgham
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Yet another try (20.62 KB, patch)
2021-02-19 13:30 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (18.25 KB, patch)
2021-02-19 15:11 PST, Brent Fulgham
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
WIP: Trying to locate test failure. (16.38 KB, patch)
2021-02-19 21:03 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
WIP: Trying to locate test failure. (18.98 KB, patch)
2021-02-19 21:21 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Logging to identify serialization error. (21.67 KB, patch)
2021-02-20 13:46 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Additional logging (25.15 KB, patch)
2021-02-20 16:14 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Now switch serializer and log (27.03 KB, patch)
2021-02-20 17:49 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (24.01 KB, patch)
2021-02-23 12:06 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (30.58 KB, patch)
2021-02-24 09:50 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (30.55 KB, patch)
2021-02-24 11:16 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (32.74 KB, patch)
2021-02-24 14:21 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (33.06 KB, patch)
2021-02-24 15:23 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch (27.80 KB, patch)
2021-02-24 17:26 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch for landing (31.09 KB, patch)
2021-02-25 12:11 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff
Patch to address Blob test (22.09 KB, patch)
2021-02-25 18:23 PST, Brent Fulgham
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brent Fulgham 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).
Comment 1 Radar WebKit Bug Importer 2021-02-18 17:07:21 PST
<rdar://problem/74500963>
Comment 2 Brent Fulgham 2021-02-18 17:11:35 PST
Created attachment 420888 [details]
Patch
Comment 3 Brent Fulgham 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).
Comment 4 Darin Adler 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;
Comment 5 Brent Fulgham 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.
Comment 6 Alex Christensen 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.
Comment 7 Brent Fulgham 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!
Comment 8 Darin Adler 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.
Comment 9 Brent Fulgham 2021-02-19 12:54:30 PST
Created attachment 421017 [details]
More complete change.
Comment 10 Brent Fulgham 2021-02-19 13:12:43 PST
Created attachment 421020 [details]
Rebaselined
Comment 11 Brent Fulgham 2021-02-19 13:21:18 PST
Created attachment 421026 [details]
Another try.
Comment 12 Brent Fulgham 2021-02-19 13:30:44 PST
Created attachment 421027 [details]
Yet another try
Comment 13 Alex Christensen 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.
Comment 14 Brent Fulgham 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.
Comment 15 Brent Fulgham 2021-02-19 15:11:44 PST
Created attachment 421042 [details]
Patch
Comment 16 Alex Christensen 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
Comment 17 Brent Fulgham 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

!!
Comment 18 Brent Fulgham 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.
Comment 19 Brent Fulgham 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.
Comment 20 Darin Adler 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.
Comment 21 Brent Fulgham 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.
Comment 22 Brent Fulgham 2021-02-19 21:03:49 PST
Created attachment 421077 [details]
WIP: Trying to locate test failure.
Comment 23 Brent Fulgham 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.
Comment 24 Brent Fulgham 2021-02-19 21:21:12 PST
Created attachment 421079 [details]
WIP: Trying to locate test failure.
Comment 25 Brent Fulgham 2021-02-20 13:46:55 PST
Created attachment 421108 [details]
Logging to identify serialization error.
Comment 26 Brent Fulgham 2021-02-20 16:14:26 PST
Created attachment 421119 [details]
Additional logging
Comment 27 Brent Fulgham 2021-02-20 17:49:39 PST
Created attachment 421122 [details]
Now switch serializer and log
Comment 28 Brent Fulgham 2021-02-23 12:06:02 PST
Created attachment 421338 [details]
Patch
Comment 29 Darin Adler 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?
Comment 30 David Kilzer (:ddkilzer) 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.
Comment 31 Brent Fulgham 2021-02-24 09:50:58 PST
Created attachment 421417 [details]
Patch
Comment 32 David Kilzer (:ddkilzer) 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.
Comment 33 Geoffrey Garen 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.
Comment 34 Brent Fulgham 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.
Comment 35 Brent Fulgham 2021-02-24 11:16:20 PST
Created attachment 421430 [details]
Patch
Comment 36 Darin Adler 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.
Comment 37 Brent Fulgham 2021-02-24 14:21:51 PST
Created attachment 421456 [details]
Patch
Comment 38 Brent Fulgham 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.
Comment 39 Brent Fulgham 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.
Comment 40 Darin Adler 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.
Comment 41 Brent Fulgham 2021-02-24 15:23:30 PST
Created attachment 421470 [details]
Patch
Comment 42 Darin Adler 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]);
Comment 43 Brent Fulgham 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.
Comment 44 Brent Fulgham 2021-02-24 17:26:34 PST
Created attachment 421486 [details]
Patch
Comment 45 Brent Fulgham 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.
Comment 46 Darin Adler 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?
Comment 47 Brent Fulgham 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).
Comment 48 Darin Adler 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.
Comment 49 Brent Fulgham 2021-02-25 12:11:27 PST
Created attachment 421553 [details]
Patch for landing
Comment 50 EWS 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].
Comment 51 WebKit Commit Bot 2021-02-25 15:50:39 PST
Re-opened since this is blocked by bug 222442
Comment 52 Brent Fulgham 2021-02-25 18:23:13 PST
Created attachment 421592 [details]
Patch to address Blob test
Comment 53 Brent Fulgham 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.
Comment 54 EWS 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].