Bug 232737

Summary: Add basic support for launching CaptivePortalMode WebProcesses
Product: WebKit Reporter: Chris Dumez <cdumez>
Component: WebKit2Assignee: Chris Dumez <cdumez>
Status: RESOLVED FIXED    
Severity: Normal CC: achristensen, bfulgham, fpizlo, ggaren, kkinnunen, thorton, webkit-bug-importer, wenson_hsieh
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 233016    
Bug Blocks: 232958    
Attachments:
Description Flags
WIP Patch
none
WIP Patch (with API test)
none
WIP Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch bfulgham: review+

Comment 1 Chris Dumez 2021-11-04 17:09:05 PDT
<rdar://84473037>
Comment 2 Chris Dumez 2021-11-04 17:13:09 PDT
Created attachment 443357 [details]
WIP Patch
Comment 3 Chris Dumez 2021-11-05 07:57:30 PDT
Created attachment 443392 [details]
WIP Patch (with API test)
Comment 4 Chris Dumez 2021-11-05 09:13:18 PDT
Created attachment 443401 [details]
WIP Patch
Comment 5 Chris Dumez 2021-11-05 09:29:41 PDT
Created attachment 443406 [details]
Patch
Comment 6 Brent Fulgham 2021-11-05 09:46:35 PDT
Comment on attachment 443406 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443406&action=review

> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:95
> +            JSC::Options::Options::useJIT() = false;

I think for miniMode we also want:

JSC::Options::Options::useGenerationalGC() = false;
JSC::Options::Options::useConcurrentGC() = false;
Comment 7 Alexey Proskuryakov 2021-11-05 09:48:39 PDT
The content of attachment 443357 [details] has been deleted
Comment 8 Alexey Proskuryakov 2021-11-05 09:48:48 PDT
The content of attachment 443392 [details] has been deleted
Comment 9 Alexey Proskuryakov 2021-11-05 09:48:58 PDT
The content of attachment 443401 [details] has been deleted
Comment 10 Chris Dumez 2021-11-05 09:57:25 PDT
Created attachment 443412 [details]
Patch
Comment 11 Tim Horton 2021-11-05 10:57:05 PDT
Comment on attachment 443412 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443412&action=review

> Source/WebKit/UIProcess/WebPageProxy.cpp:3439
> +    auto shouldEnableMiniMode = (policies ? policies->miniModeEnabled() : isMiniModeEnabledGlobally()) ? WebProcessProxy::IsMiniModeEnabled::Yes : WebProcessProxy::IsMiniModeEnabled::No;

If the global switch is not "force enable mini mode" but instead a /fallback/, why not just use the normal bit on defaultWebpagePreferences in WKWebViewConfiguration?
Comment 12 Chris Dumez 2021-11-05 11:01:53 PDT
Created attachment 443418 [details]
Patch
Comment 13 Chris Dumez 2021-11-05 11:10:14 PDT
(In reply to Tim Horton from comment #11)
> Comment on attachment 443412 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=443412&action=review
> 
> > Source/WebKit/UIProcess/WebPageProxy.cpp:3439
> > +    auto shouldEnableMiniMode = (policies ? policies->miniModeEnabled() : isMiniModeEnabledGlobally()) ? WebProcessProxy::IsMiniModeEnabled::Yes : WebProcessProxy::IsMiniModeEnabled::No;
> 
> If the global switch is not "force enable mini mode" but instead a
> /fallback/, why not just use the normal bit on defaultWebpagePreferences in
> WKWebViewConfiguration?

Captive portal mode can be enabled / disabled system wide. Then it can be overridden by browsers per-site via WKWebpagePreferences.

The issue with WKWebViewConfiguration.defaultWebpagePreferences.captivePortalModeEnabled is that it only applies to WebViews using this configuration, it is not app-global.

Also, when the client is setting captivePortalModeEnabled on a WKWebpagePreferences object, how do I know if I am supposed to set the global NSUserDefault or not? How do I differentiate the case where the client wants to set it globally vs the client wants to set it by default for all views using this WKWebViewConfiguration (or only for this navigation)?

This is why I introduced a WKWebpagePreferences._captivePortalModeEnabled class property (readwrite), so that the client can set or query the global state of the feature.
Comment 14 Chris Dumez 2021-11-05 11:34:32 PDT
(In reply to Chris Dumez from comment #13)
> (In reply to Tim Horton from comment #11)
> > Comment on attachment 443412 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=443412&action=review
> > 
> > > Source/WebKit/UIProcess/WebPageProxy.cpp:3439
> > > +    auto shouldEnableMiniMode = (policies ? policies->miniModeEnabled() : isMiniModeEnabledGlobally()) ? WebProcessProxy::IsMiniModeEnabled::Yes : WebProcessProxy::IsMiniModeEnabled::No;
> > 
> > If the global switch is not "force enable mini mode" but instead a
> > /fallback/, why not just use the normal bit on defaultWebpagePreferences in
> > WKWebViewConfiguration?
> 
> Captive portal mode can be enabled / disabled system wide. Then it can be
> overridden by browsers per-site via WKWebpagePreferences.
> 
> The issue with
> WKWebViewConfiguration.defaultWebpagePreferences.captivePortalModeEnabled is
> that it only applies to WebViews using this configuration, it is not
> app-global.
> 
> Also, when the client is setting captivePortalModeEnabled on a
> WKWebpagePreferences object, how do I know if I am supposed to set the
> global NSUserDefault or not? How do I differentiate the case where the
> client wants to set it globally vs the client wants to set it by default for
> all views using this WKWebViewConfiguration (or only for this navigation)?
> 
> This is why I introduced a WKWebpagePreferences._captivePortalModeEnabled
> class property (readwrite), so that the client can set or query the global
> state of the feature.

After discussing with Tim and Wenson offline, I think we have a simpler proposal. Reworking the patch now..
Comment 15 Chris Dumez 2021-11-05 13:30:55 PDT
Created attachment 443431 [details]
Patch
Comment 16 Tim Horton 2021-11-05 13:46:29 PDT
Comment on attachment 443431 [details]
Patch

Not sure about all of the "is" prefixes (also you have both "shouldUse" and "shouldEnable" and I think they have the same meaning?), but this seems better to me.
Comment 17 Chris Dumez 2021-11-05 14:08:11 PDT
Created attachment 443435 [details]
Patch
Comment 18 Alex Christensen 2021-11-08 16:59:12 PST
Comment on attachment 443435 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443435&action=review

> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:100
>              JSC::ExecutableAllocator::setJITEnabled(false);

This does some stronger things that we may want to do in captive portal mode.
We should also audit the users of disable-jit and see if they can migrate to this as a replacement.

> Source/WebKit/UIProcess/API/APIWebsitePolicies.h:163
> +    std::optional<bool> m_captivePortalModeEnabled;

This can just be a bool that defaults to WebKit::captivePortalModeEnabledBySystem(), right?

> Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:7630
> +// On iOS, the captive portal mode API requires a browser entitlement.

Why don't we give TestWebKitAPI this entitlement to test what happens when you have it?
Comment 19 Chris Dumez 2021-11-08 17:14:16 PST
Comment on attachment 443435 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443435&action=review

>> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:100
>>              JSC::ExecutableAllocator::setJITEnabled(false);
> 
> This does some stronger things that we may want to do in captive portal mode.
> We should also audit the users of disable-jit and see if they can migrate to this as a replacement.

> This does some stronger things that we may want to do in captive portal mode.
I don't understand this comment. Also, why are you commenting on the pre-existing disable-jit flag. I am not relying on this pre-existing disable-jit flag because we turn off more JSC features in captive portal mode. Also, in a follow-up patch, it will also impact WebCore settings, not just JSC options.

>> Source/WebKit/UIProcess/API/APIWebsitePolicies.h:163
>> +    std::optional<bool> m_captivePortalModeEnabled;
> 
> This can just be a bool that defaults to WebKit::captivePortalModeEnabledBySystem(), right?

The reason I used an std::optional<bool> is that the system setting may change during the lifetime of the APIWebsitePolicies object. If I use a bool and set the value at construction time, then we won't update it if the system setting changes.
This is especially problematic for WKWebViewConfiguration.defaultWebpagePreferences which has a long lifetime.

>> Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:7630
>> +// On iOS, the captive portal mode API requires a browser entitlement.
> 
> Why don't we give TestWebKitAPI this entitlement to test what happens when you have it?

It would be nice, yes. I don't know how to do that yet but I will look into it.
Comment 20 Alex Christensen 2021-11-08 17:16:05 PST
Comment on attachment 443435 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443435&action=review

>>> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:100
>>>              JSC::ExecutableAllocator::setJITEnabled(false);
>> 
>> This does some stronger things that we may want to do in captive portal mode.
>> We should also audit the users of disable-jit and see if they can migrate to this as a replacement.
> 
> 

I may be wrong, but I think ExecutableAllocator::setJITEnabled makes it so the process is unable to allocate executable memory even if compromised, whereas JSC::Options::useJIT() = false; just makes it so it doesn't try to under normal circumstances.
Comment 21 Chris Dumez 2021-11-08 17:18:00 PST
(In reply to Alex Christensen from comment #20)
> Comment on attachment 443435 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=443435&action=review
> 
> >>> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:100
> >>>              JSC::ExecutableAllocator::setJITEnabled(false);
> >> 
> >> This does some stronger things that we may want to do in captive portal mode.
> >> We should also audit the users of disable-jit and see if they can migrate to this as a replacement.
> > 
> > 
> 
> I may be wrong, but I think ExecutableAllocator::setJITEnabled makes it so
> the process is unable to allocate executable memory even if compromised,
> whereas JSC::Options::useJIT() = false; just makes it so it doesn't try to
> under normal circumstances.

Oh I see. I didn't understand that initially. ExecutableAllocator::setJITEnabled() may be more suitable then, I'll look into it.
Comment 22 Chris Dumez 2021-11-08 17:19:37 PST
Comment on attachment 443435 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443435&action=review

>>>>> Source/WebKit/Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceEntryPoint.h:100
>>>>>              JSC::ExecutableAllocator::setJITEnabled(false);
>>>> 
>>>> This does some stronger things that we may want to do in captive portal mode.
>>>> We should also audit the users of disable-jit and see if they can migrate to this as a replacement.
>>> 
>>> 
>> 
>> I may be wrong, but I think ExecutableAllocator::setJITEnabled makes it so the process is unable to allocate executable memory even if compromised, whereas JSC::Options::useJIT() = false; just makes it so it doesn't try to under normal circumstances.
> 
> Oh I see. I didn't understand that initially. ExecutableAllocator::setJITEnabled() may be more suitable then, I'll look into it.

If I remember correctly, the reason I used `JSC::Options::useJIT() = false` is that `[webView _isJITEnabled:(void(^)(BOOL))completionHandler]` was returning NO when using `JSC::ExecutableAllocator::setJITEnabled(false)`. This may be an issue with _isJITEnabled not properly detecting that JIT is disable though.
Comment 23 Chris Dumez 2021-11-08 17:52:51 PST
Created attachment 443642 [details]
Patch
Comment 24 Chris Dumez 2021-11-08 18:37:12 PST
Created attachment 443646 [details]
Patch
Comment 25 Chris Dumez 2021-11-08 18:38:36 PST
Per Alex's feedback:
- Now using `ExecutableAllocator::setJITEnabled(false)` instead of `JSC::Options::Options::useJIT() = false;`.
- Also giving the browser entitlement to TestWebKitAPI on iOS so I can enable the API tests on iOS as well.
Comment 26 Chris Dumez 2021-11-10 09:49:24 PST
ping review?
Comment 27 Brent Fulgham 2021-11-10 11:10:17 PST
Comment on attachment 443646 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443646&action=review

r=me

> Source/WebKit/UIProcess/API/Cocoa/WKWebpagePreferences.h:74
> +/*! @abstract A boolean indicating whether captive portal mode is enabled.

nit: Captive Portal ?

> Tools/TestWebKitAPI/Configurations/TestWebKitAPI-iOS.entitlements:14
> +        <true/>

Nit: Weird whitespace.
Comment 28 Chris Dumez 2021-11-10 11:14:37 PST
Committed r285594 (244102@main): <https://commits.webkit.org/244102@main>