Bug 1358719 - Add window resize reflow test. r=florian

MozReview-Commit-ID: 57mLswnXhC8

--HG--
extra : rebase_source : 136833da5984e9b2e5d150a497aad1d7eb632f5d
This commit is contained in:
Mike Conley 2018-03-07 13:29:25 -05:00
Родитель a2c22e61fc
Коммит 62afea2749
3 изменённых файлов: 162 добавлений и 8 удалений

Просмотреть файл

@ -30,6 +30,7 @@ run-if = debug || devedition || nightly_build # Requires startupRecorder.js, whi
skip-if = (os == 'linux') || (os == 'win' && debug) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320. skip-if = (os == 'linux') || (os == 'win' && debug) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320.
[browser_urlbar_search_reflows.js] [browser_urlbar_search_reflows.js]
skip-if = (debug || ccov) && (os == 'linux' || os == 'win') # Disabled on Linux and Windows debug and ccov due to intermittent timeouts. Bug 1414126, bug 1426611. skip-if = (debug || ccov) && (os == 'linux' || os == 'win') # Disabled on Linux and Windows debug and ccov due to intermittent timeouts. Bug 1414126, bug 1426611.
[browser_window_resize_reflows.js]
[browser_windowclose_reflows.js] [browser_windowclose_reflows.js]
[browser_windowopen_flicker.js] [browser_windowopen_flicker.js]
skip-if = (debug && os == 'win') # Disabled on windows debug for intermittent leaks skip-if = (debug && os == 'win') # Disabled on windows debug for intermittent leaks

Просмотреть файл

@ -0,0 +1,138 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
* is a whitelist that should slowly go away as we improve the performance of
* the front-end. Instead of adding more reflows to the whitelist, you should
* be modifying your code to avoid the reflow.
*
* See https://developer.mozilla.org/en-US/Firefox/Performance_best_practices_for_Firefox_fe_engineers
* for tips on how to do that.
*/
const EXPECTED_REFLOWS = [
{
stack: [
"onOverflow@resource:///modules/CustomizableUI.jsm",
],
maxCount: 48,
},
{
stack: [
"_moveItemsBackToTheirOrigin@resource:///modules/CustomizableUI.jsm",
"_onLazyResize@resource:///modules/CustomizableUI.jsm",
],
maxCount: 5,
},
{
stack: [
"_onLazyResize@resource:///modules/CustomizableUI.jsm",
],
maxCount: 4,
},
];
const gToolbar = document.getElementById("PersonalToolbar");
/**
* Sets the visibility state on the Bookmarks Toolbar, and
* waits for it to transition to fully visible.
*
* @param visible (bool)
* Whether or not the bookmarks toolbar should be made visible.
* @returns Promise
*/
async function toggleBookmarksToolbar(visible) {
let transitionPromise =
BrowserTestUtils.waitForEvent(gToolbar, "transitionend",
e => e.propertyName == "max-height");
setToolbarVisibility(gToolbar, visible);
await transitionPromise;
}
/**
* Resizes a browser window to a particular width and height, and
* waits for it to reach a "steady state" with respect to its overflowing
* toolbars.
* @param win (browser window)
* The window to resize.
* @param width (int)
* The width to resize the window to.
* @param height (int)
* The height to resize the window to.
* @returns Promise
*/
async function resizeWindow(win, width, height) {
let toolbarEvent =
BrowserTestUtils.waitForEvent(win, "BookmarksToolbarVisibilityUpdated");
let resizeEvent =
BrowserTestUtils.waitForEvent(win, "resize");
let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
dwu.ensureDirtyRootFrame();
win.resizeTo(width, height);
await resizeEvent;
forceImmediateToolbarOverflowHandling(win);
await toolbarEvent;
}
/*
* This test ensures that there are no unexpected
* uninterruptible reflows when resizing windows.
*/
add_task(async function() {
const BOOKMARKS_COUNT = 150;
const STARTING_WIDTH = 600;
const STARTING_HEIGHT = 400;
const SMALL_WIDTH = 150;
const SMALL_HEIGHT = 150;
await PlacesUtils.bookmarks.eraseEverything();
// Add a bunch of bookmarks to display in the Bookmarks toolbar
await PlacesUtils.bookmarks.insertTree({
guid: PlacesUtils.bookmarks.toolbarGuid,
children: Array(BOOKMARKS_COUNT).fill("")
.map((_, i) => ({ url: `http://test.places.${i}/`}))
});
let wasCollapsed = gToolbar.collapsed;
Assert.ok(wasCollapsed, "The toolbar is collapsed by default");
if (wasCollapsed) {
let promiseReady =
BrowserTestUtils.waitForEvent(gToolbar, "BookmarksToolbarVisibilityUpdated");
await toggleBookmarksToolbar(true);
await promiseReady;
}
registerCleanupFunction(async () => {
if (wasCollapsed) {
await toggleBookmarksToolbar(false);
}
await PlacesUtils.bookmarks.eraseEverything();
await PlacesUtils.history.clear();
});
let win = await prepareSettledWindow();
if (win.screen.availWidth < STARTING_WIDTH ||
win.screen.availHeight < STARTING_HEIGHT) {
Assert.ok(false, "This test is running on too small a display - " +
`(${STARTING_WIDTH}x${STARTING_HEIGHT} min)`);
return;
}
await resizeWindow(win, STARTING_WIDTH, STARTING_HEIGHT);
await withReflowObserver(async function() {
await resizeWindow(win, SMALL_WIDTH, SMALL_HEIGHT);
await resizeWindow(win, STARTING_WIDTH, STARTING_HEIGHT);
}, EXPECTED_REFLOWS, win);
await BrowserTestUtils.closeWindow(win);
});

Просмотреть файл

@ -199,18 +199,33 @@ async function ensureNoPreloadedBrowser(win = window) {
}); });
} }
/**
* The navigation toolbar is overflowable, meaning that some items
* will be moved and held within a sub-panel if the window gets too
* small to show their icons. The calculation for hiding those items
* occurs after resize events, and is debounced using a DeferredTask.
* This utility function allows us to fast-forward to just running
* that function for that DeferredTask instead of waiting for the
* debounce timeout to occur.
*/
function forceImmediateToolbarOverflowHandling(win) {
let overflowableToolbar = win.document.getElementById("nav-bar").overflowable;
if (overflowableToolbar._lazyResizeHandler && overflowableToolbar._lazyResizeHandler.isArmed) {
overflowableToolbar._lazyResizeHandler.disarm();
// Ensure the root frame is dirty before resize so that, if we're
// in the middle of a reflow test, we record the reflows deterministically.
let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
dwu.ensureDirtyRootFrame();
overflowableToolbar._onLazyResize();
}
}
async function prepareSettledWindow() { async function prepareSettledWindow() {
let win = await BrowserTestUtils.openNewBrowserWindow(); let win = await BrowserTestUtils.openNewBrowserWindow();
await ensureNoPreloadedBrowser(win); await ensureNoPreloadedBrowser(win);
forceImmediateToolbarOverflowHandling(win);
let overflowableToolbar = win.document.getElementById("nav-bar").overflowable;
if (overflowableToolbar._lazyResizeHandler && overflowableToolbar._lazyResizeHandler.isArmed) {
info("forcing deferred overflow handling of the navigation toolbar to happen immediately");
overflowableToolbar._lazyResizeHandler.disarm();
overflowableToolbar._onLazyResize();
}
return win; return win;
} }