Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 65e6c589b7014ac5e27f1add81f949d8e1f9c261
https://github.com/WebKit/WebKit/commit/65e6c589b7014ac5e27f1add81f949d8e1f9c261
Author: Rupin Mittal <[email protected]>
Date: 2026-06-18 (Thu, 18 Jun 2026)
Changed paths:
M LayoutTests/fast/loader/cancel-load-during-port-block-timer-expected.txt
M LayoutTests/fast/loader/cancel-load-during-port-block-timer.html
M Source/WebCore/loader/DocumentLoader.cpp
M Source/WebCore/loader/FrameLoader.cpp
M Source/WebCore/loader/LoaderStrategy.h
M Source/WebKit/Shared/WebErrors.cpp
M Source/WebKit/Shared/WebErrors.h
M Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp
M Source/WebKit/WebProcess/Network/WebLoaderStrategy.h
M Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h
M Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.mm
M Tools/TestWebKitAPI/Tests/WebKit/WKWebView/Navigation.mm
Log Message:
-----------
[Page Loading] WiFi captive popup stuck at blank screen
https://bugs.webkit.org/show_bug.cgi?id=317357
rdar://159376485
Reviewed by Brady Eidson.
When a WiFi captive network returns the URL that the user must use to
authenticate
and access the WiFi, this URL is loaded in a WebSheet via a WebView. In this
case,
nothing loads and the WebSheet remains blank.
The sysdiagnose shows that the load is being blocked because the JavaScript at
that
URL is redirecting to another URL which contains a blocked port. WebKit blocks
the
load. The issue is that WebKit doesn't notify the client (WebSheet) that this
load
has been blocked.
JavaScript initiated navigations go through FrameLoader::loadFrameRequest().
This
function early returns if the navigation is to a blocked port (this check was
added
in https://commits.webkit.org/236675@main). The problem is that this function is
called before WebKit lets the client know that a navigation has been requested
(via the decidePolicyForNavigationAction delegate), so the client (WebSheet) is
not
notified that a navigation has begun or that it failed. It can't handle the
error
and choose to show an error page. This is why the popup gets stuck at blank.
In order to notify the client, WebKit must call the
decidePolicyForNavigationAction
delegate and later the didFailProvisionalNavigation delegate. So the check for
blocked
ports must come later. And this check already exists. If we don't early return
from
FrameLoader::loadFrameRequest, we will continue on:
1. FrameLoader::loadFrameRequest
2. FrameLoader::loadURL
3. PolicyChecker::checkNavigationPolicy
4. decidePolicyForNavigationAction delegate (client allows the navigation)
5. FrameLoader::continueLoadAfterNavigationPolicy
6. FrameLoader::prepareForLoadStart
7. didStartProvisionalNavigation delegate
8. DocumentLoader::startLoadingMainResource
9. DocumentLoader::loadMainResource (DocumentLoader.cpp:2277)
10. CachedResourceLoader::requestMainResource
11. CachedResourceLoader::requestResource
--> This does the blocked port check and returns an error.
So by removing the early return in FrameLoader::loadFrameRequest(), the code
will
continue on and notify the client about the navigation.
Currently, when CachedResourceLoader::requestResource() returns the port blocked
error, DocumentLoader::loadMainResource() does not cancel the load with an error
but rather just displays an empty page. So the client is not notified that the
navigation has failed. So we modify this to cancel the load with an error so
that
the didFailProvisionalNavigation delegate will be called and allow the the
client
to handle the error as they see fit.
The fact that DocumentLoader::loadMainResource() simply loads an empty document
is also the reason why Safari will display the about:blank empty document if you
type in a URL with an invalid port in the search bar. Making the change to cause
didFailProvisionalNavigation to be called changes the behavior in Safari so that
it instead displays an error message describing that the port is blocked (this
aligns with Firefox & Chrome).
We were unable to reproduce the issue with the WiFi captive portal, but we do
have
a new API test that convers this scenario:
JSInitiatedNavigationWithRestrictedPortFailsProvisionalNavigation.
We also update the layout test cancel-load-during-port-block-timer.html
(1) The console message now no longer comes synchronously, it comes after the
client responds to the decidePolicyForNavigationAction delegate. But the
test calls document.write() which calls document.open() which stops the
policy check and the load if delegateIsDecidingNavigationPolicy. So the
port check doesn't happen anymore.
(2) It looks like the test passes if it *doesn't* crash.
* LayoutTests/fast/loader/cancel-load-during-port-block-timer-expected.txt:
* LayoutTests/fast/loader/cancel-load-during-port-block-timer.html:
* Source/WebCore/loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::loadMainResource):
* Source/WebCore/loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadFrameRequest):
* Source/WebCore/loader/LoaderStrategy.h:
* Source/WebKit/Shared/WebErrors.cpp:
(WebKit::isBlockedError):
* Source/WebKit/Shared/WebErrors.h:
* Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::isBlockedError const):
* Source/WebKit/WebProcess/Network/WebLoaderStrategy.h:
* Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h:
* Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.mm:
(WebResourceLoadScheduler::isBlockedError const):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/Navigation.mm:
(TEST(WKNavigation,
JSInitiatedNavigationWithRestrictedPortFailsProvisionalNavigation)):
Canonical link: https://commits.webkit.org/315513@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications