Verified Commit 56c2fcdb authored by ma1's avatar ma1 Committed by Pier Angelo Vendrame
Browse files

Bug 41631: Prevent weird initial window dimensions caused by subpixel computations

parent 2c6021b2
Loading
Loading
Loading
Loading
+93 −46
Original line number Diff line number Diff line
@@ -21,16 +21,31 @@ const kPrefLetterboxingGradient =

const kTopicDOMWindowOpened = "domwindowopened";

var logConsole;
function log(msg) {
  if (!logConsole) {
    logConsole = console.createInstance({
const lazy = {};

XPCOMUtils.defineLazyGetter(lazy, "logConsole", () =>
  console.createInstance({
    prefix: "RFPHelper.jsm",
    maxLogLevelPref: "privacy.resistFingerprinting.jsmloglevel",
    });
  })
);

function log(...args) {
  lazy.logConsole.log(...args);
}

  logConsole.log(msg);
function forEachWindow(callback) {
  const windowList = Services.wm.getEnumerator("navigator:browser");
  while (windowList.hasMoreElements()) {
    const win = windowList.getNext();
    if (win.gBrowser && !win.closed) {
      try {
        callback(win);
      } catch (e) {
        lazy.logConsole.error(e);
      }
    }
  }
}

class _RFPHelper {
@@ -170,7 +185,11 @@ class _RFPHelper {
      (this.rfpEnabled = Services.prefs.getBoolPref(kPrefResistFingerprinting))
    ) {
      this._addRFPObservers();
      Services.ww.registerNotification(this);
      forEachWindow(win => this._attachWindow(win));
    } else {
      forEachWindow(win => this._detachWindow(win));
      Services.ww.unregisterNotification(this);
      this._removeRFPObservers();
    }
  }
@@ -314,12 +333,12 @@ class _RFPHelper {
  }

  _handleLetterboxingPrefChanged() {
    if (Services.prefs.getBoolPref(kPrefLetterboxing, false)) {
      Services.ww.registerNotification(this);
      this._attachAllWindows();
    } else {
      this._detachAllWindows();
      Services.ww.unregisterNotification(this);
    this.letterboxingEnabled = Services.prefs.getBoolPref(
      kPrefLetterboxing,
      false
    );
    if (this.rfpEnabled) {
      forEachWindow(win => this._updateSizeForTabsInWindow(win));
    }
  }

@@ -421,11 +440,13 @@ class _RFPHelper {
    let logPrefix = `_roundContentSize[${Math.random()}]`;
    log(logPrefix);
    let win = aBrowser.ownerGlobal;

    let browserContainer = aBrowser
      .getTabBrowser()
      .getBrowserContainer(aBrowser);
    let browserParent = aBrowser.parentElement;
    browserParent.classList.remove("exclude-letterboxing");

    let [
      [contentWidth, contentHeight],
      [parentWidth, parentHeight],
@@ -438,6 +459,17 @@ class _RFPHelper {
      ])
    );

    const isInitialSize =
      win._rfpOriginalSize &&
      win.outerWidth === win._rfpOriginalSize.width &&
      win.outerHeight === win._rfpOriginalSize.height;

    // We may need to shrink this window to rounded size if the browser container
    // area is taller than the original, meaning extra chrome (like the optional
    // "Only Show on New Tab" bookmarks toobar) was present and now gone.
    const needToShrink =
      isInitialSize && containerHeight > win._rfpOriginalSize.containerHeight;

    log(
      `${logPrefix} contentWidth=${contentWidth} contentHeight=${contentHeight} parentWidth=${parentWidth} parentHeight=${parentHeight} containerWidth=${containerWidth} containerHeight=${containerHeight}${
        isNewTab ? " (new tab)." : "."
@@ -465,7 +497,10 @@ class _RFPHelper {

      log(`${logPrefix} roundDimensions(${aWidth}, ${aHeight})`);

      let result;
      if (!(isInitialSize || this.letterboxingEnabled)) {
        // just round size to int
        return r(aWidth, aHeight);
      }

      // If the set is empty, we will round the content with the default
      // stepping size.
@@ -517,9 +552,20 @@ class _RFPHelper {
            try {
              change();
            } catch (e) {
              logConsole.error(e);
              lazy.logConsole.error(e);
            }
          }
          if (needToShrink && win.shrinkToLetterbox()) {
            win.addEventListener(
              "resize",
              () => {
                // We need to record the "new" initial size in this listener
                // because resized dimensions are not immediately available.
                RFPHelper._recordWindowSize(win);
              },
              { once: true }
            );
          }
        });
      },
    });
@@ -600,7 +646,6 @@ class _RFPHelper {

  _updateSizeForTabsInWindow(aWindow) {
    let tabBrowser = aWindow.gBrowser;

    tabBrowser.tabpanels?.classList.add("letterboxing");
    tabBrowser.tabpanels?.classList.toggle(
      "letterboxing-vcenter",
@@ -618,9 +663,39 @@ class _RFPHelper {
    // we need to add this class late because otherwise new windows get maximized
    aWindow.setTimeout(() => {
      tabBrowser.tabpanels?.classList.add("letterboxing-ready");
      if (!aWindow._rfpOriginalSize) {
        this._recordWindowSize(aWindow);
      }
    });
  }

  _recordWindowSize(aWindow) {
    aWindow.promiseDocumentFlushed(() => {
      aWindow._rfpOriginalSize = {
        width: aWindow.outerWidth,
        height: aWindow.outerHeight,
        containerHeight: aWindow.gBrowser.getBrowserContainer()?.clientHeight,
      };
      log("Recording original window size", aWindow._rfpOriginalSize);
    });
  }

  // We will attach this method to each browser window. When called
  // it will instantly resize the window to exactly fit the selected
  // (possibly letterboxed) browser.
  // Returns true if a window resize will occur, false otherwise.
  shrinkToLetterbox() {
    let { selectedBrowser } = this.gBrowser;
    let stack = selectedBrowser.closest(".browserStack");
    const outer = stack.getBoundingClientRect();
    const inner = selectedBrowser.getBoundingClientRect();
    if (inner.width !== outer.witdh || inner.height !== outer.height) {
      this.resizeBy(inner.width - outer.width, inner.height - outer.height);
      return true;
    }
    return false;
  }

  _attachWindow(aWindow) {
    aWindow.gBrowser.addTabsProgressListener(this);
    aWindow.addEventListener("TabOpen", this);
@@ -638,20 +713,6 @@ class _RFPHelper {
    this._updateSizeForTabsInWindow(aWindow);
  }

  _attachAllWindows() {
    let windowList = Services.wm.getEnumerator("navigator:browser");

    while (windowList.hasMoreElements()) {
      let win = windowList.getNext();

      if (win.closed || !win.gBrowser) {
        continue;
      }

      this._attachWindow(win);
    }
  }

  _detachWindow(aWindow) {
    let tabBrowser = aWindow.gBrowser;
    tabBrowser.removeTabsProgressListener(this);
@@ -669,20 +730,6 @@ class _RFPHelper {
    }
  }

  _detachAllWindows() {
    let windowList = Services.wm.getEnumerator("navigator:browser");

    while (windowList.hasMoreElements()) {
      let win = windowList.getNext();

      if (win.closed || !win.gBrowser) {
        continue;
      }

      this._detachWindow(win);
    }
  }

  _handleDOMWindowOpened(win) {
    let self = this;