Open Bug 1592238 Opened 5 years ago Updated 2 years ago

Repeatedly reloading on htmledit.squarefree.com causes exponential frameset growth

Categories

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

70 Branch
defect

Tracking

()

ASSIGNED

People

(Reporter: nyanpasu64, Assigned: smaug)

References

(Regression, )

Details

(Keywords: regression)

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0

Steps to reproduce:

Actual results:

When I first visited the page, there were 2 panels.
When I reloaded, each panel was subdivided into 2 panels (giving 4 total), then the subdivisions disappeared, leaving 2 panels total.
When I reloaded again, there were 8 panels, before the page went to normal (2 panels). Then 16, then 32...

After 4 page loads (3 reloads), the page took around a second to start up. Then 1.5 seconds. Then 3 seconds, and so on...

Expected results:

Reloading the page should not cause more than 2 panels to appear. This issue does not occur in Chrome or Edge.

https://htmledit.squarefree.com/ uses a frameset, not iframes.

According to my tests at https://www.browserling.com , the issue appeared between Firefox 66 and 67.

Status: UNCONFIRMED → NEW
Has Regression Range: --- → yes
Has STR: --- → yes
Component: Untriaged → DOM: Core & HTML
Ever confirmed: true
Keywords: regression
Product: Firefox → Core
Regressed by: 1489308
Flags: needinfo?(bzbarsky)

The basic structure of the page is that it has two <frame> elements with src="javascript:''". Then onload it writes the actual content into those frames with document.write. Per spec, that causes the URLs of the documents in those iframes to be the URL of the document doing the write (that is, the parent), and in particular to not match the URL in the src attribute. The difference from pre-bug 1489308 behavior is that we used to create wyciwyg URLs for the subframe documents which represented the written-out content.

Now we reload the page. The toplevel page is parsed and creates two frame elements. Session history then starts loading the "last loaded" thing in those subframes, which in this case is the URL of the parent page. That creates two more frame elements per frame element; we don't have session history entries for them yet, so they just load javascript:''. Then the load event for the subframes fires before the toplevel load event (of course), and does the document.write bits in those sub-subframes, creating session history entries for them. So the next reload we load the toplevel URL in all four of those sub-subframes, etc. Again, the difference from pre-bug 1489308 is that we used to have reload put the text of the document.write in the subframes, not the toplevel page itself.

The difference in behavior from Chrome and Edge is that a reload in those browsers does not reload the "last loaded" URL in subframes, but rather reloads the original src, as far as I know. That means that if you navigate a subframe and then reload, in Firefox your navigation will not be lost and in Chrome/Edge it will be. See also bug 356558.

I see a few options here. One would be to flag the SHEntries resulting from a document.open as "don't reload this in iframes, use the src" in some way, since there's no really good way to make that make any sense. Another would be to apply the same recursion restrictions we apply to src attributes when we're doing session history loads, which would block the recursive loads in this case, and then when the page load event fires the writes into the iframes would happen.

Olli, any thoughts on which of those is easier/better? Or any other suggestions? Special-casing the document.open session history entries seems least likely to cause fallout elsewhere...

Flags: needinfo?(bzbarsky) → needinfo?(bugs)
Attached file Simple testcase

This testcase makes the onload writes conditional, to make it easier to see what's going on.

Oh, and here's a testcase for the general "reload after subframe navigation" behavior:

<!doctype html>
<iframe src="data:text/html,<a href='http://example.com'>Click me</a>"></iframe>

Load that, click the link, reload, via either browser UI or the button. Observe the behavior difference between Chrome and Firefox.

Could we perhaps reuse nsISHEntry::IsDynamicallyAdded() or nsDocShell::SetCreatedDynamically
Method should perhaps be renamed then, but the idea is similar - don't try to use session history entry for the relevant "dynamic" iframe.

Will upload a WIP which helps with https://htmledit.squarefree.com/
but haven't thought about what it could break.

Component: DOM: Core & HTML → DOM: Navigation
Flags: needinfo?(bugs)

The priority flag is not set for this bug.
:neha, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(nkochar)

Olli, assigning to you since you've started looking into this and also, looks pretty bad and something we should fix sooner rather than later.

Assignee: nobody → bugs
Status: NEW → ASSIGNED
Flags: needinfo?(nkochar)
Priority: -- → P2
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: