Preserve sticky user activation across same-origin navigations - #63952
Conversation
|
EWS run on previous version of this PR (hash 73cedee) Details |
macOS Safer C++ Build #98696 (73cedee)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
iOS Safer C++ Build #17028 (73cedee)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
73cedee to
998a01e
Compare
|
EWS run on previous version of this PR (hash 998a01e) Details |
998a01e to
d163889
Compare
|
EWS run on previous version of this PR (hash d163889) Details |
d163889 to
869b58d
Compare
|
EWS run on previous version of this PR (hash 869b58d) Details |
869b58d to
b9584ea
Compare
|
EWS run on previous version of this PR (hash b9584ea) Details |
b9584ea to
cc4b6a6
Compare
|
EWS run on previous version of this PR (hash cc4b6a6) Details |
| @@ -7032,6 +7028,8 @@ imported/w3c/web-platform-tests/html/user-activation/navigation-state-reset-cros | |||
| imported/w3c/web-platform-tests/html/user-activation/navigation-state-reset-sameorigin.html [ Skip ] | |||
| imported/w3c/web-platform-tests/html/user-activation/user-activation-interface.html [ Skip ] | |||
| imported/w3c/web-platform-tests/html/user-activation/activation-same-and-cross-origin.sub.html [ Skip ] | |||
| imported/w3c/web-platform-tests/html/user-activation/navigate-to-crossorigin-redirect.html [ Skip ] | |||
| imported/w3c/web-platform-tests/html/user-activation/navigate-to-sameorigin.html [ Skip ] | |||
There was a problem hiding this comment.
Both tests rely on test_driver.click() to give the popup window user activation before navigating it. PR #63430 enabled popup-window click dispatch via eventSender, but only for the non-iOS path. the iOS WK2 path goes through iController.singleTapAtPoint, which targets the main test view only and has no popup-view-aware equivalent, so it was not covered by that fix. As a result, on iOS the test's precondition never holds. The popup never reaches the activated state, and the assertions about preserving sticky activation across navigation can't be exercised. The tests fail at the activation setup step, not at the behavior we're shipping.
Also, this matches a pre-existing convention in LayoutTests/platform/ios/TestExpectations, which already groups several user-activation WPTs under the comment:
# UserActivation tests rely on test_driver.click() which is not supported on iOS
The two new tests (navigate-to-sameorigin.html, navigate-to-crossorigin-redirect.html) are skipped under that same group for the same reason.
| @@ -5,5 +5,5 @@ Tests that navigating a same-origin child frame resets its activation states. | |||
| Click inside the yellow area. | |||
|
|
|||
|
|
|||
| PASS Post-navigation state reset. | |||
| FAIL Post-navigation state reset. assert_false: expected false got true | |||
There was a problem hiding this comment.
This needs some kind of explanation as to why this is not a regression.
There was a problem hiding this comment.
Thank you for the careful review.
My reading of the spec PR discussion is that sticky activation preservation is intended to apply per-frame, including iframes. In particular, the response in LINK to the question of restricting it to top-level only leans against that restriction:
"I'm less sure about this. My instinct was to just do whatever was easiest to spec/implement, which in this case was to allow it to work in iframes."
and in LINK
"On iframes, it seems simpler to just allow those navigations to carry over sticky activation."
Based on those, my implementation in DocumentWriter::begin() applies uniformly to both top-level and iframe navigations.
About navigation-state-reset-sameorigin.html: this test exercises a same-origin iframe navigation (not top-level) and asserts that sticky activation is reset — which I read as reflecting the pre-spec-change behavior. Under my reading of the new spec, sticky activation should be preserved in iframe navigations as well, so the test's existing assertion no longer holds. The expected.txt update to FAIL documents this transitional state until WPT upstream is updated to match the new spec.
If you read the spec discussion differently, please let us know — happy to revisit the scope.
Thanks again!
| && previousWindow && previousWindow->hasStickyActivation() && existingDocument) { | ||
| bool wasRedirected = false; | ||
| if (RefPtr documentLoader = frameLoader->documentLoader()) | ||
| wasRedirected = documentLoader->originalURL() != documentLoader->responseURL(); |
There was a problem hiding this comment.
This is not robust. In theory the URL could be the same, but a redirect could have taken place due to a cookie or some such.
I'm also not sure this is the correct place to make this overall check. Maybe @youennf can give some pointers.
There was a problem hiding this comment.
Thanks for catching this. I hadn't accounted for that case. I'll revisit the redirect detection and follow up with an updated patch.
Thanks.
There was a problem hiding this comment.
Addressed both concerns in the latest push:
-
Redirect detection is no longer based on URL equality between originalURL() and responseURL(). The check now uses NetworkLoadMetrics::hasCrossOriginRedirect, which is set to true whenever any step in the redirect chain crosses an origin boundary (regardless of whether the final URL happens to match the start URL). This correctly handles A → B → A patterns and stops blocking legitimate same-origin internal redirects.
-
Additionally added a check that the navigation is renderer-initiated. Browser-initiated navigations (address bar typing, bookmarks, history navigation, embedder API loads) now suppress carry-over via DocumentLoader::isRequestFromClientOrUserInput(). This aligns with Chromium's behavior.
Regarding your second comment (whether DocumentWriter::begin() is the right place for this check) — with the URL-equality removed, the check now reads only from the navigation's own DocumentLoader (initiator flag, redirect metrics) and the previous Document/Window (origin, sticky activation). All of this is per-Document state that is naturally available at navigation commit time. Happy to revisit the location if you still see a better fit.
Not in this PR (planned follow-up): The spec discussion also calls for the carry-over to apply when a document is reactivated from the back/forward cache, so that behavior remains consistent between bfcache hits and misses. This PR only updates the "create new document" path (DocumentWriter::begin()); WebKit's bfcache restore path is a separate code site that I plan to address in a follow-up once the spec text for the reactivate algorithm is finalized.
cc4b6a6 to
162f6c9
Compare
|
EWS run on previous version of this PR (hash 162f6c9) Details |
162f6c9 to
fb801cd
Compare
|
EWS run on previous version of this PR (hash fb801cd) Details |
|
Moving this to draft. Plan to (1) add bfcache restore coverage, and (2) drop the Chromium-aligned bits that aren't actually in the spec text (whatwg/html#11454), keeping the implementation strictly spec-faithful. Will re-request review once both are sorted. Thanks! |
fb801cd to
db9860c
Compare
|
EWS run on previous version of this PR (hash db9860c) Details |
|
@annevk Thanks, |
There was a problem hiding this comment.
This WPT now requires preserving sticky activation in subframes too — will update WebKit accordingly:
https://github.com/web-platform-tests/wpt/pull/60008/changes
db9860c to
2075bcb
Compare
|
EWS run on previous version of this PR (hash 2075bcb) Details |
iOS Safer C++ Build #35491 (2075bcb)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
macOS Safer C++ Build #116892 (2075bcb)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
2075bcb to
6c25c8c
Compare
|
EWS run on previous version of this PR (hash 6c25c8c) Details |
iOS Safer C++ Build #38185 (6c25c8c)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
macOS Safer C++ Build #119354 (6c25c8c)❌ Found 1 failing file with 1 issue. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming. |
https://bugs.webkit.org/show_bug.cgi?id=313716 Reviewed by NOBODY (OOPS!). Implement sticky user activation carry-over per whatwg/html#11454, centralized in LocalDOMWindow::carryOverStickyActivationFromPreviousWindow and applied at two entry points: - DocumentWriter::begin carries sticky activation onto a same-origin destination, suppressed when the redirect chain crossed origins (guards A -> B -> A confused-deputy patterns). - FrameLoader::open(CachedFrameBase&) applies the same rule on bfcache reactivation; no network load, so the redirect suppressor is N/A. Builds on the explicit sticky/history-action activation booleans on LocalDOMWindow (bug 316317); carry-over sets m_hasStickyActivation on the destination window when the source had sticky activation and the navigation stayed same-origin. Only sticky activation is carried over, not transient or history-action. Gated behind StickyUserActivationAcrossSameOriginNavigationsEnabled (testable, off by default, auto-enabled in WebKitTestRunner). * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/web-platform-tests/html/user-activation/navigate-to-crossorigin-redirect-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/user-activation/navigate-to-sameorigin-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/user-activation/navigation-state-reset-sameorigin-expected.txt: * LayoutTests/platform/ios/TestExpectations: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebCore/loader/DocumentWriter.cpp: * Source/WebCore/loader/FrameLoader.cpp: * Source/WebCore/page/LocalDOMWindow.cpp: * Source/WebCore/page/LocalDOMWindow.h:
6c25c8c to
5db185b
Compare
|
EWS run on current version of this PR (hash 5db185b) Details |
|
Hi @youennf The spec PR has already been reviewed by @annevk and is expected to be merged soon. I’ve updated the implementation accordingly, and the new behavior is currently guarded as default-off/testable, so it should not affect existing behavior by default. Your review would be appreciated when you have a chance. Thanks! |
db9860c
5db185b