summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_windowopen_reflows.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/general/browser_windowopen_reflows.js')
-rw-r--r--browser/base/content/test/general/browser_windowopen_reflows.js117
1 files changed, 117 insertions, 0 deletions
diff --git a/browser/base/content/test/general/browser_windowopen_reflows.js b/browser/base/content/test/general/browser_windowopen_reflows.js
new file mode 100644
index 000000000..7dac8aad6
--- /dev/null
+++ b/browser/base/content/test/general/browser_windowopen_reflows.js
@@ -0,0 +1,117 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const EXPECTED_REFLOWS = [
+ // handleEvent flushes layout to get the tabstrip width after a resize.
+ "handleEvent@chrome://browser/content/tabbrowser.xml|",
+
+ // Loading a tab causes a reflow.
+ "loadTabs@chrome://browser/content/tabbrowser.xml|" +
+ "loadOneOrMoreURIs@chrome://browser/content/browser.js|" +
+ "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+
+ // Selecting the address bar causes a reflow.
+ "select@chrome://global/content/bindings/textbox.xml|" +
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
+ "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+
+ // Focusing the content area causes a reflow.
+ "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|",
+
+ // Sometimes sessionstore collects data during this test, which causes a sync reflow
+ // (https://bugzilla.mozilla.org/show_bug.cgi?id=892154 will fix this)
+ "ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm",
+];
+
+if (Services.appinfo.OS == "WINNT" || Services.appinfo.OS == "Darwin") {
+ // TabsInTitlebar._update causes a reflow on OS X and Windows trying to do calculations
+ // since layout info is already dirty. This doesn't seem to happen before
+ // MozAfterPaint on Linux.
+ EXPECTED_REFLOWS.push("TabsInTitlebar._update/rect@chrome://browser/content/browser-tabsintitlebar.js|" +
+ "TabsInTitlebar._update@chrome://browser/content/browser-tabsintitlebar.js|" +
+ "updateAppearance@chrome://browser/content/browser-tabsintitlebar.js|" +
+ "handleEvent@chrome://browser/content/tabbrowser.xml|");
+}
+
+if (Services.appinfo.OS == "Darwin") {
+ // _onOverflow causes a reflow getting widths.
+ EXPECTED_REFLOWS.push("OverflowableToolbar.prototype._onOverflow@resource:///modules/CustomizableUI.jsm|" +
+ "OverflowableToolbar.prototype.init@resource:///modules/CustomizableUI.jsm|" +
+ "OverflowableToolbar.prototype.observe@resource:///modules/CustomizableUI.jsm|" +
+ "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|");
+ // Same as above since in packaged builds there are no function names and the resource URI includes "app"
+ EXPECTED_REFLOWS.push("@resource://app/modules/CustomizableUI.jsm|" +
+ "@resource://app/modules/CustomizableUI.jsm|" +
+ "@resource://app/modules/CustomizableUI.jsm|" +
+ "gBrowserInit._delayedStartup@chrome://browser/content/browser.js|");
+}
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when opening new windows.
+ */
+function test() {
+ waitForExplicitFinish();
+
+ // Add a reflow observer and open a new window
+ let win = OpenBrowserWindow();
+ let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+ docShell.addWeakReflowObserver(observer);
+
+ // Wait until the mozafterpaint event occurs.
+ waitForMozAfterPaint(win, function paintListener() {
+ // Remove reflow observer and clean up.
+ docShell.removeWeakReflowObserver(observer);
+ win.close();
+
+ finish();
+ });
+}
+
+var observer = {
+ reflow: function (start, end) {
+ // Gather information about the current code path.
+ let stack = new Error().stack;
+ let path = stack.split("\n").slice(1).map(line => {
+ return line.replace(/:\d+:\d+$/, "");
+ }).join("|");
+ let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
+
+ // Stack trace is empty. Reflow was triggered by native code.
+ if (path === "") {
+ return;
+ }
+
+ // Check if this is an expected reflow.
+ for (let expectedStack of EXPECTED_REFLOWS) {
+ if (path.startsWith(expectedStack) ||
+ // Accept an empty function name for gBrowserInit._delayedStartup or TabsInTitlebar._update to workaround bug 906578.
+ path.startsWith(expectedStack.replace(/(^|\|)(gBrowserInit\._delayedStartup|TabsInTitlebar\._update)@/, "$1@"))) {
+ ok(true, "expected uninterruptible reflow '" + expectedStack + "'");
+ return;
+ }
+ }
+
+ ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
+ },
+
+ reflowInterruptible: function (start, end) {
+ // We're not interested in interruptible reflows.
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
+ Ci.nsISupportsWeakReference])
+};
+
+function waitForMozAfterPaint(win, callback) {
+ win.addEventListener("MozAfterPaint", function onEnd(event) {
+ if (event.target != win)
+ return;
+ win.removeEventListener("MozAfterPaint", onEnd);
+ executeSoon(callback);
+ });
+}