tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_tabdetach.js (3932B)


      1 "use strict";
      2 
      3 /**
      4 * WHOA THERE: We should never be adding new things to EXPECTED_REFLOWS. This
      5 * list should slowly go away as we improve the performance of the front-end.
      6 * Instead of adding more reflows to the list, you should be modifying your code
      7 * to avoid the reflow.
      8 *
      9 * See https://firefox-source-docs.mozilla.org/performance/bestpractices.html
     10 * for tips on how to do that.
     11 */
     12 const EXPECTED_REFLOWS = [
     13  {
     14    stack: [
     15      "clientPos@chrome://browser/content/tabbrowser/drag-and-drop.js",
     16      "startTabDrag@chrome://browser/content/tabbrowser/drag-and-drop.js",
     17      "handle_dragstart@chrome://browser/content/tabbrowser/drag-and-drop.js",
     18      "on_dragstart@chrome://browser/content/tabbrowser/tabs.js",
     19      "handleEvent@chrome://browser/content/tabbrowser/tabs.js",
     20      "synthesizeMouseAtPoint@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     21      "synthesizeMouse@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     22      "synthesizePlainDragAndDrop@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     23    ],
     24    maxCount: 2,
     25  },
     26 
     27  {
     28    stack: [
     29      "get scrollPosition@chrome://global/content/elements/arrowscrollbox.js",
     30      "startTabDrag@chrome://browser/content/tabbrowser/drag-and-drop.js",
     31      "handle_dragstart@chrome://browser/content/tabbrowser/drag-and-drop.js",
     32      "on_dragstart@chrome://browser/content/tabbrowser/tabs.js",
     33      "handleEvent@chrome://browser/content/tabbrowser/tabs.js",
     34      "synthesizeMouseAtPoint@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     35      "synthesizeMouse@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     36      "synthesizePlainDragAndDrop@chrome://mochikit/content/tests/SimpleTest/EventUtils.js",
     37    ],
     38  },
     39 ];
     40 
     41 /**
     42 * This test ensures that there are no unexpected uninterruptible reflows when
     43 * detaching a tab via drag and drop. The first testcase tests a non-overflowed
     44 * tab strip, and the second tests an overflowed one.
     45 */
     46 
     47 add_task(async function test_detach_not_overflowed() {
     48  await ensureNoPreloadedBrowser();
     49  await createTabs(1);
     50 
     51  // Make sure we didn't overflow, as expected
     52  await TestUtils.waitForCondition(() => {
     53    return !gBrowser.tabContainer.overflowing;
     54  });
     55 
     56  let win;
     57  await withPerfObserver(
     58    async function () {
     59      win = await detachTab(gBrowser.tabs[1]);
     60    },
     61    {
     62      expectedReflows: EXPECTED_REFLOWS,
     63      // we are opening a whole new window, so there's no point in tracking
     64      // rects being painted
     65      frames: { filter: () => [] },
     66    }
     67  );
     68 
     69  await BrowserTestUtils.closeWindow(win);
     70  win = null;
     71 });
     72 
     73 add_task(async function test_detach_overflowed() {
     74  const TAB_COUNT_FOR_OVERFLOW = computeMaxTabCount();
     75  await createTabs(TAB_COUNT_FOR_OVERFLOW + 1);
     76 
     77  // Make sure we overflowed, as expected
     78  await TestUtils.waitForCondition(() => {
     79    return gBrowser.tabContainer.overflowing;
     80  });
     81 
     82  let win;
     83  await withPerfObserver(
     84    async function () {
     85      win = await detachTab(
     86        gBrowser.tabs[Math.floor(TAB_COUNT_FOR_OVERFLOW / 2)]
     87      );
     88    },
     89    {
     90      expectedReflows: EXPECTED_REFLOWS,
     91      // we are opening a whole new window, so there's no point in tracking
     92      // rects being painted
     93      frames: { filter: () => [] },
     94    }
     95  );
     96 
     97  await BrowserTestUtils.closeWindow(win);
     98  win = null;
     99 
    100  await removeAllButFirstTab();
    101 });
    102 
    103 async function detachTab(tab) {
    104  let newWindowPromise = BrowserTestUtils.waitForNewWindow();
    105 
    106  await EventUtils.synthesizePlainDragAndDrop({
    107    srcElement: tab,
    108 
    109    // destElement is null because tab detaching happens due
    110    // to a drag'n'drop on an invalid drop target.
    111    destElement: null,
    112 
    113    // don't move horizontally because that could cause a tab move
    114    // animation, and there's code to prevent a tab detaching if
    115    // the dragged tab is released while the animation is running.
    116    stepX: 0,
    117    stepY: 100,
    118  });
    119 
    120  return newWindowPromise;
    121 }