Skip to content

Support for out-of-process iframes in Firefox#9672

Merged
michaelDCurran merged 2 commits into
nvaccess:masterfrom
jcsteh:fission
Nov 11, 2019
Merged

Support for out-of-process iframes in Firefox#9672
michaelDCurran merged 2 commits into
nvaccess:masterfrom
jcsteh:fission

Conversation

@jcsteh

@jcsteh jcsteh commented Jun 5, 2019

Copy link
Copy Markdown
Contributor

Link to issue number:

None.

Summary of the issue:

Firefox is adding support for out-of-process iframes; i.e. iframes rendered in a separate process to their embedder document. For an out-of-process iframe, the embedder has no knowledge of children in the embedded document and cannot communicate with the embedded document at all. This means that accChild for accessibles in the embedded document fails. This requires some changes to the gecko_ia2 virtual buffer.

Description of how this pull request fixes the issue:

In the gecko_ia2 vbuf:

  1. getNVDAObjectFromIdentifier: Use getNVDAObjectFromEvent instead of accChild on the document. This was changed last year to use accChild on the document in the theoretical hope that it might be slightly faster, since it doesn't need to go via the parent process. However, this was never proved to be a performance benefit in real terms. The root accessible is in the parent process and can fetch children in all content documents, so using AccessibleObjectFromEvent works as expected.
  2. __contains__: If accChild fails, get the embedder iframe and try accChild with the iframe's id. There can be nested out-of-process iframes, so we keep trying this until there are no more embedders in the hierarchy (or until we hit the buffer's root id).

Testing performed:

  1. Loaded a document with two out-of-process iframes in one tab and a document with no iframes in another tab. In the Python console, saved the former document's TreeInterceptor as ti1 and the latter document's TreeInterceptor as ti2; e.g. ti1 = nav.treeInterceptor.
  2. Moved the navigator object to a node in the innermost iframe and pressed NVDA+control+z to take a console snapshot.
  3. Confirmed that nav in ti1 is True and nav in ti2 is False.
  4. Moved the navigator object to a node in the document with no iframes and pressed NVDA+control+z.
  5. Confirmed that nav in ti1 is False and nav in ti2 is True.

Also used a build with this change for a while doing some daily browsing with Gmail, GitHub, etc.

Known issues with pull request:

There will be some additional COM calls for objects in out-of-process iframes. However, there don't tend to be many levels of nested iframes, so I don't anticipate this will be a significant issue in reality.

Other avenues explored:

Originally, I tried having __contains__ check the buffer itself to see if it contains the node in question. This also had to check ancestors (limited at an arbitrary number for performance) just in case the buffer hasn't caught up yet or in case we chose not to render descendants in the buffer.

  1. I was uncomfortable with the arbitrary ancestor check limit, even though it's necessary for performance. With the new approach, we don't have to worry about performance as much because iframes generally aren't nested deeply (whereas nodes on a page often are).
  2. This approach caused major problems when a buffer was being loaded. I didn't dig into this much, but I guess the buffer was reporting that nodes didn't exist (which makes total sense while it's loading). This would certainly confuse things because the focus would be reported as not being within the buffer.

Change log entry:

Changes:

- Support for out-of-process iframes in Mozilla Firefox.

jcsteh added 2 commits June 5, 2019 12:36
…t instead of accChild on the document.

This was changed to use accChild on the document in the theoretical hope that it might be slightly faster, since it doesn't need to go via the parent process.
However, this was never proved to be a performance benefit in real terms.
In Firefox, when an iframe document is rendered in a separate process to its embedder, the embedder has no knowledge of children in the embedded document and cannot communicate with the embedded document at all.
This means that accChild for accessibles in the embedded document fails.
The root accessible is in the parent process and can fetch children in all content documents, so using AccessibleObjectFromEvent works as expected.
…me(s).

In Firefox, when an iframe document is rendered in a separate process to its embedder, accChild for accessibles in the embedded document fails.
If this is the case, we can get the embedder iframe and try accChild with the iframe's id.
There can be nested out-of-process iframes, so we keep trying this until there are no more embedders in the hierarchy (or until we hit the buffer's root id).
@jcsteh jcsteh requested a review from michaelDCurran June 5, 2019 04:18
@michaelDCurran

Copy link
Copy Markdown
Member

I take it that out-of-process support is already available in Firefox nightlies? is there anything special one must do to enable these, or will any iFrames do this by default?

@jcsteh

jcsteh commented Jun 5, 2019 via email

Copy link
Copy Markdown
Contributor Author

@michaelDCurran michaelDCurran left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good. But I'll leave this unmerged until this feature is a little more public.

@michaelDCurran

Copy link
Copy Markdown
Member

Currently in Firefox nightly 71, if I enable fission.autostart, restart nightly and go to https://www.nvaccess.org/
I do not see the youtube video frame in browse mode at all. Nor can I find it with object navigation. Yet, I can find the Twitter widget frame. Is this expected behaviour?

@michaelDCurran

Copy link
Copy Markdown
Member

Tabbing to the Youtube frame however does, in NVDA master at least, cause a new browseMode document to be created for just the youtube frame. I have not specifically tested with this pr yet.

@jcsteh

jcsteh commented Sep 10, 2019 via email

Copy link
Copy Markdown
Contributor Author

@michaelDCurran

michaelDCurran commented Sep 10, 2019 via email

Copy link
Copy Markdown
Member

@jcsteh

jcsteh commented Sep 10, 2019 via email

Copy link
Copy Markdown
Contributor Author

@michaelDCurran

michaelDCurran commented Sep 10, 2019 via email

Copy link
Copy Markdown
Member

@jcsteh

jcsteh commented Nov 4, 2019

Copy link
Copy Markdown
Contributor Author

This turned out to be a lot more difficult to track down than I thought. It was actually not the problem I originally thought it was. Anyway, it's now fixed; see https://bugzilla.mozilla.org/show_bug.cgi?id=1581441. I also fixed another bug that could cause similar behaviour, but was very different behind the scenes; see https://bugzilla.mozilla.org/show_bug.cgi?id=1581040.

@michaelDCurran, would you mind taking another look at this? Thanks.

@michaelDCurran michaelDCurran merged commit 71475bc into nvaccess:master Nov 11, 2019
@nvaccessAuto nvaccessAuto added this to the 2019.3 milestone Nov 11, 2019
michaelDCurran added a commit that referenced this pull request Nov 11, 2019
jcsteh added a commit that referenced this pull request Nov 25, 2019
michaelDCurran pushed a commit that referenced this pull request Nov 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants