Skip to content

Commit ea022c4

Browse files
Bug 1825745 - Make form submits do a replace load if they happen before document load has ended. r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D174224
1 parent ffa1503 commit ea022c4

File tree

6 files changed

+71
-17
lines changed

6 files changed

+71
-17
lines changed

docshell/base/nsDocShell.cpp

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -971,10 +971,21 @@ bool nsDocShell::MaybeHandleSubframeHistory(
971971
// executing an onLoad Handler,this load will not go
972972
// into session history.
973973
// XXX Why is this code in a method which deals with iframes!
974-
bool inOnLoadHandler = false;
975-
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
976-
if (inOnLoadHandler) {
977-
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
974+
if (aLoadState->IsFormSubmission()) {
975+
#ifdef DEBUG
976+
if (!mEODForCurrentDocument) {
977+
const MaybeDiscarded<BrowsingContext>& targetBC =
978+
aLoadState->TargetBrowsingContext();
979+
MOZ_ASSERT_IF(GetBrowsingContext() == targetBC.get(),
980+
aLoadState->LoadType() == LOAD_NORMAL_REPLACE);
981+
}
982+
#endif
983+
} else {
984+
bool inOnLoadHandler = false;
985+
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
986+
if (inOnLoadHandler) {
987+
aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
988+
}
978989
}
979990
}
980991
return false;
@@ -8561,7 +8572,7 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
85618572
// Explicit principal because we do not want any guesses as to what the
85628573
// principal to inherit is: it should be aTriggeringPrincipal.
85638574
loadState->SetPrincipalIsExplicit(true);
8564-
loadState->SetLoadType(LOAD_LINK);
8575+
loadState->SetLoadType(aLoadState->LoadType());
85658576
loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
85668577
INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
85678578

@@ -8613,6 +8624,11 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
86138624
}
86148625

86158626
aLoadState->SetTargetBrowsingContext(targetContext);
8627+
if (aLoadState->IsFormSubmission()) {
8628+
aLoadState->SetLoadType(
8629+
GetLoadTypeForFormSubmission(targetContext, aLoadState));
8630+
}
8631+
86168632
//
86178633
// Transfer the load to the target BrowsingContext... Clear the window target
86188634
// name to the empty string to prevent recursive retargeting!
@@ -9226,6 +9242,20 @@ static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
92269242
return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
92279243
}
92289244

9245+
uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9246+
BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9247+
MOZ_ASSERT(aLoadState->IsFormSubmission());
9248+
9249+
// https://html.spec.whatwg.org/#form-submission-algorithm
9250+
// 22. Let historyHandling be "push".
9251+
// 23. If form document equals targetNavigable's active document, and
9252+
// form document has not yet completely loaded, then set
9253+
// historyHandling to "replace".
9254+
return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9255+
? LOAD_NORMAL_REPLACE
9256+
: LOAD_LINK;
9257+
}
9258+
92299259
nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
92309260
Maybe<uint32_t> aCacheKey) {
92319261
MOZ_ASSERT(aLoadState, "need a load state!");
@@ -9265,6 +9295,8 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
92659295
return PerformRetargeting(aLoadState);
92669296
}
92679297

9298+
// This is the non-retargeting load path, we've already set the right loadtype
9299+
// for form submissions in nsDocShell::OnLinkClickSync.
92689300
if (aLoadState->TargetBrowsingContext().IsNull()) {
92699301
aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
92709302
}
@@ -13084,11 +13116,24 @@ nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
1308413116
CopyUTF8toUTF16(type, typeHint);
1308513117
}
1308613118

13087-
// Link click (or form submission) can be triggered inside an onload
13088-
// handler, and we don't want to add history entry in this case.
13089-
bool inOnLoadHandler = false;
13090-
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13091-
uint32_t loadType = inOnLoadHandler ? LOAD_NORMAL_REPLACE : LOAD_LINK;
13119+
uint32_t loadType = LOAD_LINK;
13120+
if (aLoadState->IsFormSubmission()) {
13121+
if (aLoadState->Target().IsEmpty()) {
13122+
// We set the right load type here for form submissions with an empty
13123+
// target. Form submission with a non-empty target are handled in
13124+
// nsDocShell::PerformRetargeting after we've selected the correct target
13125+
// BC.
13126+
loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13127+
}
13128+
} else {
13129+
// Link click can be triggered inside an onload handler, and we don't want
13130+
// to add history entry in this case.
13131+
bool inOnLoadHandler = false;
13132+
GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13133+
if (inOnLoadHandler) {
13134+
loadType = LOAD_NORMAL_REPLACE;
13135+
}
13136+
}
1309213137

1309313138
nsCOMPtr<nsIReferrerInfo> referrerInfo =
1309413139
elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())

docshell/base/nsDocShell.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,13 @@ class nsDocShell final : public nsDocLoader,
710710
nsresult ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
711711
nsACString& aNewHash, uint32_t aLoadType);
712712

713+
// This returns the load type for a form submission (see
714+
// https://html.spec.whatwg.org/#form-submission-algorithm). The load type
715+
// should be set as soon as the target BC has been determined.
716+
uint32_t GetLoadTypeForFormSubmission(
717+
mozilla::dom::BrowsingContext* aTargetBC,
718+
nsDocShellLoadState* aLoadState);
719+
713720
private:
714721
// Returns true if would have called FireOnLocationChange,
715722
// but did not because aFireOnLocationChange was false on entry.

docshell/test/mochitest/file_bug1773192_2.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
<form method="POST" action="file_bug1773192_3.sjs"></form>
88
<script>
99
history.replaceState({}, "", document.referrer);
10-
document.forms[0].submit();
10+
setTimeout(() => {
11+
// The test relies on this page not going into the BFCache, so that
12+
// when we come back to it we load the URL from the replaceState
13+
// instead.
14+
window.blockBFCache = new RTCPeerConnection();
15+
document.forms[0].submit();
16+
}, 0);
1117
</script>
1218
</body>
1319
</html>
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
[form-requestsubmit.html]
22
expected:
33
if (os == "android") and fission: [OK, TIMEOUT]
4-
[Replace before load, triggered by formElement.requestSubmit()]
5-
expected: FAIL
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
[form-submit-button-click.html]
22
expected:
33
if (os == "android") and fission: [OK, TIMEOUT]
4-
[Replace before load, triggered by submitButton.click()]
5-
expected: FAIL
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[form-submit.html]
2-
[Replace before load, triggered by same-document formElement.submit()]
3-
expected: FAIL
2+
expected:
3+
if (os == "android") and fission: [OK, TIMEOUT]

0 commit comments

Comments
 (0)