Open Bug 1703580 Opened 3 years ago Updated 2 months ago

Firefox does not act on history.pushState calls during a (Service Worker) navigation event

Categories

(Core :: DOM: Navigation, defect, P3)

Firefox 87
defect

Tracking

()

UNCONFIRMED

People

(Reporter: cm.jasonyoung, Unassigned, NeedInfo)

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36

Steps to reproduce:

We have a service worker that is intercepting navigation events. For certain ones, we will return a 204 response and use postMessage to send the tab different data to render. In order to update the url and create a history entry, we use history.pushState.

Actual results:

When history.pushState is called while the browser is waiting for the navigation event to end (after the fetch event in the service worker but before the 204 response), the url will change but the history entry will not be created. If history.pushState is called via a setTimeout, both the url and the history entry will be updated.

Expected results:

In Chrome/Edge and Safari, calling history.pushState during a navigation event will update both the history entry and the url. We're not sure if this is the intended behavior for Firefox or if it is a bug. We haven't found any documentation on this so I'm submitting it as a bug report given the difference in behavior between browsers.

The Bugbug bot thinks this bug should belong to the 'Core::DOM: Navigation' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → DOM: Navigation
Product: Firefox → Core

cm.jasonyoung, thank you for the report. Would you be able to submit a testcase for this behavior which can help us to quickly identify and fix the issue?

Flags: needinfo?(cm.jasonyoung)

Hi Neha, sorry for the delay. I've attached the requested test case. In order to use it, do the following:

  1. Unzip the file
  2. Open a terminal in the folder
  3. Run npm i
  4. Run npm start
  5. Go to http://127.0.0.1:8080/page1 in Chrome or Safari
  6. Click on the Page 1 and Page 2 links a few times
  7. Verify you see the body changing and history entries being created
  8. Go to http://127.0.0.1:8080/page1 in Firefox
  9. Click on the Page 1 and Page 2 links a few times
  10. Verify you see the body changing but no history entries being created
  11. Modify the history call in page1.html and page2.html to be setTimeout(() => history.pushState({}, document.title, url), 100);
  12. Unregister the service worker and refresh the page
  13. Click on the Page 1 and Page 2 links a few times
  14. Verify you see the body changing and history entries being created

I believe this shows both Firefox's behavior is different from Chrome and Safari and that history.pushState does work after the navigation event has been processed. Please let me know if you need any more information.

Flags: needinfo?(cm.jasonyoung)

Thanks for the test case! That's a big help.

We need to determine whether the HTML standard specifies how to handle history.pushState calls during a navigation event and whether this problem happens during a regular navigation without a Service Worker.

Severity: -- → S3
Flags: needinfo?(bugs)
Priority: -- → P3
Summary: Firefox does not act on pushState calls during a navigation event → Firefox does not act on history.pushState calls during a (Service Worker) navigation event
Attached file Min test case, no sw

Hi Chris,

I've attached another test case, showing the different behavior for Firefox without a service worker. To use it, please do the following:

  1. Unzip the file
  2. Open a terminal in the folder
  3. Run npm i
  4. Run npm start
  5. Go to http://localhost:8080/page1 in Chrome or Safari
  6. Click on the Page 1 and Page 2 links
  7. Verify you see 2 history entries created for each page navigation
  8. Go to http://localhost:8080/page1 in Firefox
  9. Click on the Page 1 and Page 2 links
  10. Verify you see only 1 history entry created for each page navigation.
    Note that the response is always delayed by 1 second and the push state is delayed by 100 ms, which means it is always called after the navigation has started but before the response is received by the browser.

Looking at https://html.spec.whatwg.org/#shared-history-push/replace-state-steps, the main restrictions seems to be around preventing abuse by setting rate-limits/maximum history entries/rejecting too-large states. Since the tab is active and the pushState is being called because of a user action, I believe this should be allowed.

Hi, I was wondering what the next step for this is. Do you need any more information from me or we waiting for someone to have time to look into this?

(In reply to Jason Young from comment #6)

Hi, I was wondering what the next step for this is. Do you need any more information from me or we waiting for someone to have time to look into this?

Hi Jason, I think we are just waiting for a Mozilla engineer to investigate. Unfortunately, I don't have an ETA.

(In reply to Chris Peterson [:cpeterson] from comment #7)

(In reply to Jason Young from comment #6)

Hi, I was wondering what the next step for this is. Do you need any more information from me or we waiting for someone to have time to look into this?

Hi Jason, I think we are just waiting for a Mozilla engineer to investigate. Unfortunately, I don't have an ETA.

Ok sounds good. I just wanted to make sure I wasn't holding this up. Thanks for the update!

I don't know what navigation event is this talking. Asuth, perhaps you do?

Flags: needinfo?(smaug) → needinfo?(bugmail)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: