browser/base/content/test/general/browser_tabopen_reflows.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 XPCOMUtils.defineLazyGetter(this, "docShell", () => {
     5   return window.QueryInterface(Ci.nsIInterfaceRequestor)
     6                .getInterface(Ci.nsIWebNavigation)
     7                .QueryInterface(Ci.nsIDocShell);
     8 });
    10 const EXPECTED_REFLOWS = [
    11   // tabbrowser.adjustTabstrip() call after tabopen animation has finished
    12   "adjustTabstrip@chrome://browser/content/tabbrowser.xml|" +
    13     "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
    14     "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
    16   // switching focus in updateCurrentBrowser() causes reflows
    17   "updateCurrentBrowser@chrome://browser/content/tabbrowser.xml|" +
    18     "onselect@chrome://browser/content/browser.xul|",
    20   // switching focus in openLinkIn() causes reflows
    21   "openLinkIn@chrome://browser/content/utilityOverlay.js|" +
    22     "openUILinkIn@chrome://browser/content/utilityOverlay.js|" +
    23     "BrowserOpenTab@chrome://browser/content/browser.js|",
    25   // accessing element.scrollPosition in _fillTrailingGap() flushes layout
    26   "get_scrollPosition@chrome://global/content/bindings/scrollbox.xml|" +
    27     "_fillTrailingGap@chrome://browser/content/tabbrowser.xml|" +
    28     "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
    29     "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
    31   // The TabView iframe causes reflows in the parent document.
    32   "iQClass_height@chrome://browser/content/tabview.js|" +
    33     "GroupItem_getContentBounds@chrome://browser/content/tabview.js|" +
    34     "GroupItem_shouldStack@chrome://browser/content/tabview.js|" +
    35     "GroupItem_arrange@chrome://browser/content/tabview.js|" +
    36     "GroupItem_add@chrome://browser/content/tabview.js|" +
    37     "GroupItems_newTab@chrome://browser/content/tabview.js|" +
    38     "TabItem__reconnect@chrome://browser/content/tabview.js|" +
    39     "TabItem@chrome://browser/content/tabview.js|" +
    40     "TabItems_link@chrome://browser/content/tabview.js|" +
    41     "TabItems_init/this._eventListeners.open@chrome://browser/content/tabview.js|",
    43   // SessionStore.getWindowDimensions()
    44   "ssi_getWindowDimension@resource:///modules/sessionstore/SessionStore.jsm|" +
    45     "ssi_updateWindowFeatures/<@resource:///modules/sessionstore/SessionStore.jsm|" +
    46     "ssi_updateWindowFeatures@resource:///modules/sessionstore/SessionStore.jsm|" +
    47     "ssi_collectWindowData@resource:///modules/sessionstore/SessionStore.jsm|",
    49   // tabPreviews.capture()
    50   "tabPreviews_capture@chrome://browser/content/browser.js|" +
    51     "tabPreviews_handleEvent/<@chrome://browser/content/browser.js|",
    53   // tabPreviews.capture()
    54   "tabPreviews_capture@chrome://browser/content/browser.js|" +
    55     "@chrome://browser/content/browser.js|"
    56 ];
    58 const PREF_PRELOAD = "browser.newtab.preload";
    59 const PREF_NEWTAB_DIRECTORYSOURCE = "browser.newtabpage.directorySource";
    61 /*
    62  * This test ensures that there are no unexpected
    63  * uninterruptible reflows when opening new tabs.
    64  */
    65 function test() {
    66   waitForExplicitFinish();
    68   Services.prefs.setBoolPref(PREF_PRELOAD, false);
    69   Services.prefs.setCharPref(PREF_NEWTAB_DIRECTORYSOURCE, "data:application/json,{}");
    70   registerCleanupFunction(() => {
    71     Services.prefs.clearUserPref(PREF_PRELOAD);
    72     Services.prefs.clearUserPref(PREF_NEWTAB_DIRECTORYSOURCE);
    73   });
    75   // Add a reflow observer and open a new tab.
    76   docShell.addWeakReflowObserver(observer);
    77   BrowserOpenTab();
    79   // Wait until the tabopen animation has finished.
    80   waitForTransitionEnd(function () {
    81     // Remove reflow observer and clean up.
    82     docShell.removeWeakReflowObserver(observer);
    83     gBrowser.removeCurrentTab();
    85     finish();
    86   });
    87 }
    89 let observer = {
    90   reflow: function (start, end) {
    91     // Gather information about the current code path.
    92     let path = (new Error().stack).split("\n").slice(1).map(line => {
    93       return line.replace(/:\d+:\d+$/, "");
    94     }).join("|");
    95     let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
    97     // Stack trace is empty. Reflow was triggered by native code.
    98     if (path === "") {
    99       return;
   100     }
   102     // Check if this is an expected reflow.
   103     for (let stack of EXPECTED_REFLOWS) {
   104       if (path.startsWith(stack)) {
   105         ok(true, "expected uninterruptible reflow '" + stack + "'");
   106         return;
   107       }
   108     }
   110     ok(false, "unexpected uninterruptible reflow '" + pathWithLineNumbers + "'");
   111   },
   113   reflowInterruptible: function (start, end) {
   114     // We're not interested in interruptible reflows.
   115   },
   117   QueryInterface: XPCOMUtils.generateQI([Ci.nsIReflowObserver,
   118                                          Ci.nsISupportsWeakReference])
   119 };
   121 function waitForTransitionEnd(callback) {
   122   let tab = gBrowser.selectedTab;
   123   tab.addEventListener("transitionend", function onEnd(event) {
   124     if (event.propertyName === "max-width") {
   125       tab.removeEventListener("transitionend", onEnd);
   126       executeSoon(callback);
   127     }
   128   });
   129 }

mercurial