Bug 1262946 - Don't focus the initial browser of a new window until it has painted. r?Gijs
This is in order to optimize the critical path (the presenting of content to the user).
If we don't wait until the content has been presented for the tab switch, then we run
the risk of causing the content to send sync IPC messages for IME up to the parent,
which slows down the rendering of the content.
MozReview-Commit-ID: B0anKV8YVUz
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1178,17 +1178,34 @@ var gBrowserInit = {
Services.telemetry.getHistogramById("E10S_WINDOW").add(gMultiProcessBrowser);
SidebarUI.startDelayedLoad();
UpdateUrlbarSearchSplitterState();
if (!(isBlankPageURL(uriToLoad) || uriToLoad == "about:privatebrowsing") ||
!focusAndSelectUrlBar()) {
- gBrowser.selectedBrowser.focus();
+ if (gBrowser.selectedBrowser.isRemoteBrowser) {
+ // If the initial browser is remote, in order to optimize for first paint,
+ // we'll defer switching focus to that browser until it has painted.
+ let focusedElement = document.commandDispatcher.focusedElement;
+ let mm = window.messageManager;
+ mm.addMessageListener("Browser:FirstPaint", function onFirstPaint() {
+ mm.removeMessageListener("Browser:FirstPaint", onFirstPaint);
+ // If focus didn't move while we were waiting for first paint, we're okay
+ // to move to the browser.
+ if (document.commandDispatcher.focusedElement == focusedElement) {
+ gBrowser.selectedBrowser.focus();
+ }
+ });
+ } else {
+ // If the initial browser is not remote, we can focus the browser
+ // immediately with no paint performance impact.
+ gBrowser.selectedBrowser.focus();
+ }
}
// Enable/Disable auto-hide tabbar
gBrowser.tabContainer.updateVisibility();
BookmarkingUI.init();
gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false);
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -848,8 +848,13 @@ var RefreshBlocker = {
RefreshBlocker.init();
ExtensionContent.init(this);
addEventListener("unload", () => {
ExtensionContent.uninit(this);
RefreshBlocker.uninit();
});
+
+addEventListener("MozAfterPaint", function onFirstPaint() {
+ removeEventListener("MozAfterPaint", onFirstPaint);
+ sendAsyncMessage("Browser:FirstPaint");
+});