summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/general/browser_tabopen_reflows.js
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /browser/base/content/test/general/browser_tabopen_reflows.js
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'browser/base/content/test/general/browser_tabopen_reflows.js')
-rw-r--r--browser/base/content/test/general/browser_tabopen_reflows.js157
1 files changed, 157 insertions, 0 deletions
diff --git a/browser/base/content/test/general/browser_tabopen_reflows.js b/browser/base/content/test/general/browser_tabopen_reflows.js
new file mode 100644
index 000000000..8e04cf12e
--- /dev/null
+++ b/browser/base/content/test/general/browser_tabopen_reflows.js
@@ -0,0 +1,157 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+XPCOMUtils.defineLazyGetter(this, "docShell", () => {
+ return window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShell);
+});
+
+const EXPECTED_REFLOWS = [
+ // tabbrowser.adjustTabstrip() call after tabopen animation has finished
+ "adjustTabstrip@chrome://browser/content/tabbrowser.xml|" +
+ "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
+ "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
+
+ // switching focus in updateCurrentBrowser() causes reflows
+ "_adjustFocusAfterTabSwitch@chrome://browser/content/tabbrowser.xml|" +
+ "updateCurrentBrowser@chrome://browser/content/tabbrowser.xml|" +
+ "onselect@chrome://browser/content/browser.xul|",
+
+ // switching focus in openLinkIn() causes reflows
+ "openLinkIn@chrome://browser/content/utilityOverlay.js|" +
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
+ "BrowserOpenTab@chrome://browser/content/browser.js|",
+
+ // accessing element.scrollPosition in _fillTrailingGap() flushes layout
+ "get_scrollPosition@chrome://global/content/bindings/scrollbox.xml|" +
+ "_fillTrailingGap@chrome://browser/content/tabbrowser.xml|" +
+ "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
+ "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
+
+ // SessionStore.getWindowDimensions()
+ "ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm|" +
+ "ssi_updateWindowFeatures/<@resource:///modules/sessionstore/SessionStore.jsm|" +
+ "ssi_updateWindowFeatures@resource:///modules/sessionstore/SessionStore.jsm|" +
+ "ssi_collectWindowData@resource:///modules/sessionstore/SessionStore.jsm|",
+
+ // selection change notification may cause querying the focused editor content
+ // by IME and that will cause reflow.
+ "select@chrome://global/content/bindings/textbox.xml|" +
+ "focusAndSelectUrlBar@chrome://browser/content/browser.js|" +
+ "openLinkIn@chrome://browser/content/utilityOverlay.js|" +
+ "openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
+ "BrowserOpenTab@chrome://browser/content/browser.js|",
+
+];
+
+const PREF_PRELOAD = "browser.newtab.preload";
+const PREF_NEWTAB_DIRECTORYSOURCE = "browser.newtabpage.directory.source";
+
+/*
+ * This test ensures that there are no unexpected
+ * uninterruptible reflows when opening new tabs.
+ */
+add_task(function*() {
+ let DirectoryLinksProvider = Cu.import("resource:///modules/DirectoryLinksProvider.jsm", {}).DirectoryLinksProvider;
+ let NewTabUtils = Cu.import("resource://gre/modules/NewTabUtils.jsm", {}).NewTabUtils;
+ let Promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+
+ // resolves promise when directory links are downloaded and written to disk
+ function watchLinksChangeOnce() {
+ let deferred = Promise.defer();
+ let observer = {
+ onManyLinksChanged: () => {
+ DirectoryLinksProvider.removeObserver(observer);
+ NewTabUtils.links.populateCache(() => {
+ NewTabUtils.allPages.update();
+ deferred.resolve();
+ }, true);
+ }
+ };
+ observer.onDownloadFail = observer.onManyLinksChanged;
+ DirectoryLinksProvider.addObserver(observer);
+ return deferred.promise;
+ }
+
+ let gOrigDirectorySource = Services.prefs.getCharPref(PREF_NEWTAB_DIRECTORYSOURCE);
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref(PREF_PRELOAD);
+ Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, gOrigDirectorySource);
+ return watchLinksChangeOnce();
+ });
+
+ Services.prefs.setBoolPref(PREF_PRELOAD, false);
+ // set directory source to dummy/empty links
+ Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, 'data:application/json,{"test":1}');
+
+ // run tests when directory source change completes
+ yield watchLinksChangeOnce();
+
+ // Perform a click in the top left of content to ensure the mouse isn't
+ // hovering over any of the tiles
+ let target = gBrowser.selectedBrowser;
+ let rect = target.getBoundingClientRect();
+ let left = rect.left + 1;
+ let top = rect.top + 1;
+
+ let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ utils.sendMouseEvent("mousedown", left, top, 0, 1, 0, false, 0, 0);
+ utils.sendMouseEvent("mouseup", left, top, 0, 1, 0, false, 0, 0);
+
+ // Add a reflow observer and open a new tab.
+ docShell.addWeakReflowObserver(observer);
+ BrowserOpenTab();
+
+ // Wait until the tabopen animation has finished.
+ yield waitForTransitionEnd();
+
+ // Remove reflow observer and clean up.
+ docShell.removeWeakReflowObserver(observer);
+ gBrowser.removeCurrentTab();
+});
+
+var observer = {
+ reflow: function (start, end) {
+ // Gather information about the current code path.
+ let path = (new Error().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 stack of EXPECTED_REFLOWS) {
+ if (path.startsWith(stack)) {
+ ok(true, "expected uninterruptible reflow '" + stack + "'");
+ 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 waitForTransitionEnd() {
+ return new Promise(resolve => {
+ let tab = gBrowser.selectedTab;
+ tab.addEventListener("transitionend", function onEnd(event) {
+ if (event.propertyName === "max-width") {
+ tab.removeEventListener("transitionend", onEnd);
+ resolve();
+ }
+ });
+ });
+}