Bug 1181475 - [e10s] Shift + back/forward button opens page in a new window but renders blank
This seems to be because the docshell on the newly created browser window is inactive when it should be active. This is because with non-e10s, when we swap docshells, adding a docshell X as a child to another active docshell Y makes X be active. We don't get that automatic behaviour with e10s.

Huh… so forcing the docshell to be enabled after a remote frameloader swap doesn't appear to be enough. :( Other stuff is up.

It seems… racy…?

It just flat out doesn't seem to work, despite having the docShell be active.

What is the missing piece?

Hypothesis:

The TabStateFlusher flush Promise is not resolving before we tear the new tab out and swap the frameloaders, and this is introducing the non-determinism.

Test:

Add two second delay before calling replaceTabWithWindow in duplicateTabIn in browser.js.

Result:

Always won the race - content loaded every time.

This bolsters the hypothesis that it is SessionStore.duplicateTab kicking off a Promise that does not resolve in time.

Hypothesis:

When the TabStateFlusher flush Promise resolves before the new browser window can call swapBrowsersAndCloseOther, then the race is won, and the content is shown.

When the TabStateFlusher flush Promise resolves AFTER the new browser window calls swapBrowsersAndCloseOther, the race is lost, and the content is somehow not shown.

Test:
  • We can delay the TabStateFlusher flush Promise resolution.
  • We can delay the calling of swapBrowsersAndCloseOther

Result:

When delaying the swapBrowsersAndCloseOther, we reliably displayed the content. When we kept that delay, but added an additional delay to the TabStateFlusher flush Promise resolution, we reliably failed to display the content.

CONCLUSION:

Something in the resolution handler for SessionStore.duplicateTab is necessary in order for duplicateTabIn to work properly, and it's not occurring fast enough.

Question?: Why is this not affecting non-e10s?

Answer: I believe this is because with non-e10s we're just winning the race more often.

Ideas for solutions:

  1. Add a new method to SessionStore that is like… duplicateTabAsync that returns a Promise that resolves with the newTab, then have browser.js wait for that resolution before calling replaceTabWithWindow

From Mossop:

"This code is a little inefficient. Create a new tab in the current window, create a new window, swap tab into the new window. We can make it better and fix this bug at the same time, no SessionStore changes required:

1. Create new window
2. Duplicate tab into new window
3. Close new window's initial tab"

Ah! Easy peasy! Mossop even gave me r+ before my try build came in!

https://treeherder.mozilla.org/#/jobs?repo=try&revision=56bff499d891

Huh. Some perma orange. Wtf.

Huh… I thought opening a browser window would go through nsXULWindow::CreateNewContentWindow, which (I believe) spins a nested event loop until the XUL has all finished loading. That's not the case.

This try build is better: https://treeherder.mozilla.org/#/jobs?repo=try&revision=c27b4c9ee0fd