Closed Bug 1995636 Opened 9 months ago Closed 6 months ago

Firefox throws from history APIS (e.g. pushState, replaceState) if it's been called rapidly enough to trigger the rate-limit

Categories

(Core :: DOM: Navigation, defect)

defect

Tracking

()

RESOLVED FIXED
149 Branch
Tracking Status
firefox-esr115 --- fixed
firefox-esr140 --- fixed
firefox148 --- fixed
firefox149 --- fixed

People

(Reporter: dholbert, Assigned: farre)

References

(Regressed 1 open bug)

Details

(Keywords: webcompat:platform-bug)

User Story

user-impact-score:648

Attachments

(5 files, 1 obsolete file)

STR:

  1. Load attached testcase.
  2. (optional) Check web console.

EXPECTED RESULTS:
500 calls to pushState.
No exception thrown.

ACTUAL RESULTS:
200 calls to pushState.
Exception is thrown (which is why we stop at 200).

This is tracked in https://github.com/livewire/livewire/discussions/7746 . One comment there suggests flagging Firefox as unsupported as a result.

In bug 1993517 comment 6, we've got a bug where a Swedish banking site seems to be blocking Firefox-on-Windows due to this behavior:

  // windows firefox produce recursive navigation error
  // Too many calls to location or history APIs in a short period of time
  // https://github.com/livewire/livewire/discussions/7746
  if (isWindows && isFirefox) {
    return <BankIDViewFirefoxError />;
  }

(Windows is relevant there because the bank seems to optionally use a native Windows app, which they communicate with from the browser somehow; not sure if via a local web server or something else.)

Not sure whether it'd be prudent for us to change behavior here, but I wanted to file this since it's at least a behavioral difference with Chromium that's causing enough web-developer-trouble that Firefox is blocked in at least that one case.

Attached file testcase 1

Safari-on-macOS behaves like Firefox here, with an even stricter threshold - they throw after 100 calls to the history API, in my testcase. (And https://github.com/livewire/livewire/discussions/7746 does mention Safari as being affected, too.)

Chrome seems to be the only engine (among the major 3) to have no limit here to never throw exceptions here.

[Edited to clarify -- it's not that Chrome has no limit, but rather that they just make these history APIs silently-do-nothing when they've reached their limit.]

Summary: Firefox throws from `history.pushState` if it's been called rapidly enough to trigger the rate-limit → Firefox throws from history APIS (e.g. pushState, replaceState) if it's been called rapidly enough to trigger the rate-limit

Thanks. Looks like Chrome is willing to match the WebKit/Gecko spec-compliant behavior, per that whatwg issue, though they haven't had any recent activity on their bug ( https://issues.chromium.org/issues/40554715 ). Maybe this is a good reason to nudge them to adapt - that will hopefully push sites to handle this better rather than blocking specific browsers as is potentially the case in bug 1993517.

I was wondering how/why sites would even be running up against this - https://github.com/livewire/livewire/discussions/7746#discussioncomment-10389123 describes one scenario:

  • "a ParentComponent that loads X amount of ChildComponents" (where X = 100)
  • "all of the ChildComponents [store] state in the url search"
  • So presumably each ChildComponent uses the history API once or twice to store some data in the location.search object (the string after the ? in the URL); and since there are 100 child-components, that means there are at least 100 such calls; and if these happen in rapid succession and surpass the browser's threshold, then one of the history API invocations will throw (if the browser is Safari or Firefox).
  • ...and If I'm understanding https://github.com/whatwg/html/issues/11108 correctly, current Chromium will currently just treat the throttled invocations as no-ops and some of the ChildComponent state will be silently lost instead of stored in the URL.
User Story: (updated)

I commented in the Chromium issue.

Severity: -- → S3

We could increase the limit to, say, 1000. Pages can still hit the limit, but it's less likely. The limit was intended to not be reached by accident, but it seems from this issue it has been reached by accident.

But it does tell the site has a bug. Someone is misusing the API.
We could still use 1000, sure.

User Story: (updated)
User Story: (updated)
Assignee: nobody → afarre
Status: NEW → ASSIGNED
Pushed by amarc@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/f613aa6b6140 https://hg.mozilla.org/integration/autoland/rev/ae421aa8ee44 Revert "Bug 1995636 - Increase navigation rate limiting threshold. r=smaug" for causing wpt failures @ history_pushstate_too_many_calls.optional.html

Backed out for causing wpt failures

Flags: needinfo?(afarre)
Regressions: 2013022
Flags: needinfo?(afarre)
Pushed by abutkovits@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/60eb935df843 https://hg.mozilla.org/integration/autoland/rev/43e9ea3e063e Revert "Bug 1995636 - Increase navigation rate limiting threshold. r=smaug" for causing failures at history_replacestate_too_many_calls.optional.html.
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/57415 for changes under testing/web-platform/tests
Pushed by chorotan@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/f2fcc4ff3fbc https://hg.mozilla.org/integration/autoland/rev/69ee01432c73 Revert "Bug 1995636 - Increase navigation rate limiting threshold. r=smaug,zcorpan" for causing wpt failures on replaceState-inside-back-handler-infinite.optional.html

Backed out for causing wpt failures on replaceState-inside-back-handler-infinite.optional.html
Backout link
Push with failures
Failure log(s)

Upstream PR merged by moz-wptsync-bot
Flags: needinfo?(afarre)
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/57439 for changes under testing/web-platform/tests
Status: ASSIGNED → RESOLVED
Closed: 6 months ago
Resolution: --- → FIXED
Target Milestone: --- → 149 Branch
Upstream PR merged by moz-wptsync-bot
Regressions: 2013668

:farre, could you consider adding a beta uplift request on this if it's low risk?
It seems to fix a few web compact issues

Flags: needinfo?(afarre)
Attachment #9541993 - Flags: approval-mozilla-beta?

firefox-beta Uplift Approval Request

  • User impact if declined: Less web compatibility
  • Code covered by automated testing: yes
  • Fix verified in Nightly: yes
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: It's a preference change, allowing for more calls to pushState and replaceState during a set period of time.
  • String changes made/needed: None
  • Is Android affected?: yes
Attachment #9541994 - Flags: approval-mozilla-release?

Thanks for the remainder.

I went ahead and requested release, and the esr:s as well. It's small enough to warrant inclusion on all of them. Sounds good?

Flags: needinfo?(afarre)

firefox-release Uplift Approval Request

  • User impact if declined: Less web compatibility
  • Code covered by automated testing: yes
  • Fix verified in Nightly: yes
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: It's a preference change, allowing for more calls to pushState and replaceState during a set period of time.
  • String changes made/needed: None
  • Is Android affected?: yes
Attachment #9541993 - Flags: approval-mozilla-beta? → approval-mozilla-beta+

:farre, it looks like you wanted to created uplift requests for ESR115/ESR140, but they failed due to conflicts.
See details here https://lando.moz.tools/D281585/

Flags: needinfo?(afarre)

I also don't think this is an appropriate item to backport to ESR115 as it reaches EOL (assuming it's even affected in the first place?)

Attachment #9543061 - Flags: approval-mozilla-esr140?

firefox-esr140 Uplift Approval Request

  • User impact if declined: Less web compatibility
  • Code covered by automated testing: yes
  • Fix verified in Nightly: yes
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: It's a preference change, allowing for more calls to pushState and replaceState during a set period of time.
  • String changes made/needed: None
  • Is Android affected?: yes

(In reply to Donal Meehan [:dmeehan] from comment #31)

:farre, it looks like you wanted to created uplift requests for ESR115/ESR140, but they failed due to conflicts.
See details here https://lando.moz.tools/D281585/

Thanks, fixed and followed resolution steps. As Ryan says, we should not consider this for 115.

Flags: needinfo?(afarre)
Flags: needinfo?(dmeehan)
Flags: needinfo?(dmeehan)
Attachment #9543061 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
Attachment #9541994 - Attachment is obsolete: true
Attachment #9541994 - Flags: approval-mozilla-release?
Attachment #9560613 - Flags: approval-mozilla-esr115?

firefox-esr115 Uplift Approval Request

  • User impact if declined/Reason for urgency: Less web compatibility
  • Code covered by automated testing?: yes
  • Fix verified in Nightly?: yes
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: It's a preference change, allowing for more calls to pushState and replaceState during a set period of time.
  • String changes made/needed?: None
  • Is Android affected?: yes
Attachment #9560613 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
QA Whiteboard: [qa-triage-done-c151/b150]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: