Bug 1950362 - Fix transition-in-hidden-page.html. r=view-transitions-reviewers,boris

Reject InvalidStateError for this case as per spec, and run the view
transition page visibility change steps.

Differential Revision: https://phabricator.services.mozilla.com/D239529
This commit is contained in:
Emilio Cobos Álvarez
2025-02-25 22:48:31 +00:00
parent 90fa7916f7
commit 4f7bc12c71
4 changed files with 45 additions and 25 deletions

View File

@@ -16179,28 +16179,52 @@ bool Document::SetOrientationPendingPromise(Promise* aPromise) {
return true;
}
void Document::MaybeSkipTransitionAfterVisibilityChange() {
if (Hidden() && mActiveViewTransition) {
mActiveViewTransition->SkipTransition(SkipTransitionReason::DocumentHidden);
}
}
// https://html.spec.whatwg.org/#update-the-visibility-state
void Document::UpdateVisibilityState(DispatchVisibilityChange aDispatchEvent) {
dom::VisibilityState oldState = mVisibilityState;
mVisibilityState = ComputeVisibilityState();
if (oldState != mVisibilityState) {
if (aDispatchEvent == DispatchVisibilityChange::Yes) {
nsContentUtils::DispatchTrustedEvent(this, this, u"visibilitychange"_ns,
CanBubble::eYes, Cancelable::eNo);
}
NotifyActivityChanged();
if (mVisibilityState == dom::VisibilityState::Visible) {
MaybeActiveMediaComponents();
}
const dom::VisibilityState visibilityState = ComputeVisibilityState();
if (mVisibilityState == visibilityState) {
// 1. If document's visibility state equals visibilityState, then return.
return;
}
// 2. Set document's visibility state to visibilityState.
mVisibilityState = visibilityState;
if (aDispatchEvent == DispatchVisibilityChange::Yes) {
// 3. Fire an event named visibilitychange at document, with its bubbles
// attribute initialized to true.
nsContentUtils::DispatchTrustedEvent(this, this, u"visibilitychange"_ns,
CanBubble::eYes, Cancelable::eNo);
}
// TODO 4. Run the screen orientation change steps with document.
bool visible = !Hidden();
for (auto* listener : mWorkerListeners) {
listener->OnVisible(visible);
}
// 5. Run the view transition page visibility change steps with document.
// https://drafts.csswg.org/css-view-transitions/#view-transition-page-visibility-change-steps
const bool visible = !Hidden();
if (mActiveViewTransition && !visible) {
// The mActiveViewTransition check is an optimization: We don't allow
// creating transitions while the doc is hidden.
Dispatch(
NewRunnableMethod("MaybeSkipTransitionAfterVisibilityChange", this,
&Document::MaybeSkipTransitionAfterVisibilityChange));
}
// https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-visibility
if (!visible) {
UnlockAllWakeLocks(WakeLockType::Screen);
}
NotifyActivityChanged();
if (visible) {
MaybeActiveMediaComponents();
}
for (auto* listener : mWorkerListeners) {
listener->OnVisible(visible);
}
// https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-visibility
if (!visible) {
UnlockAllWakeLocks(WakeLockType::Screen);
}
}

View File

@@ -3868,6 +3868,7 @@ class Document : public nsINode,
void ClearActiveViewTransition();
void PerformPendingViewTransitionOperations();
void EnsureViewTransitionOperationsHappen();
void MaybeSkipTransitionAfterVisibilityChange();
// Getter for PermissionDelegateHandler. Performs lazy initialization.
PermissionDelegateHandler* GetPermissionDelegateHandler();

View File

@@ -1205,7 +1205,7 @@ void ViewTransition::SkipTransition(
"Skipped ViewTransition due to another transition starting");
break;
case SkipTransitionReason::DocumentHidden:
readyPromise->MaybeRejectWithAbortError(
readyPromise->MaybeRejectWithInvalidStateError(
"Skipped ViewTransition due to document being hidden");
break;
case SkipTransitionReason::Timeout:

View File

@@ -1,8 +1,3 @@
[transition-in-hidden-page.html]
expected:
if (os == "android"): ERROR
[A view transition should be immediately skipped if started when document is hidden]
expected: FAIL
[A view transition should be skipped when a document becomes hidden while processing update callback]
expected: FAIL