Commit aa526601 authored by Brendan Dahl's avatar Brendan Dahl
Browse files

Bug 1434077 - Inline indicators overlay. r=Paolo

This is part of the work to remove XUL overlays. The overlay was originally
created to help startup performance, but inlining the overlay seems to
no longer have detrimental effects to performance and is more straightforward.

MozReview-Commit-ID: 7sfVel6qvgv

--HG--
extra : rebase_source : b6311cf1fb98851b4f4203c314ae9ecc8160d766
parent bd38c4bf
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -928,7 +928,20 @@
                       overflows="false"
                       cui-areatype="toolbar"
                       hidden="true"
                       tooltip="dynamic-shortcut-tooltip"/>
                       tooltip="dynamic-shortcut-tooltip"
                       indicator="true">
            <!-- The panel's anchor area is smaller than the outer button, but must
                 always be visible and must not move or resize when the indicator
                 state changes, otherwise the panel could change its position or lose
                 its arrow unexpectedly. -->
            <stack id="downloads-indicator-anchor"
                   consumeanchor="downloads-button">
              <box id="downloads-indicator-icon"/>
              <stack id="downloads-indicator-progress-outer">
                <box id="downloads-indicator-progress-inner"/>
              </stack>
            </stack>
          </toolbarbutton>

        <toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
                       removable="true"
+25 −123
Original line number Diff line number Diff line
@@ -13,10 +13,6 @@
 * DownloadsPanel
 * Main entry point for the downloads panel interface.
 *
 * DownloadsOverlayLoader
 * Allows loading the downloads panel and the status indicator interfaces on
 * demand, to improve startup performance.
 *
 * DownloadsView
 * Builds and updates the downloads list widget, responding to changes in the
 * download state and real-time data.  In addition, handles part of the user
@@ -103,14 +99,9 @@ var DownloadsPanel = {
  get kStateWaitingData() {
    return 2;
  },
  /** The panel is almost shown - we're just waiting to get a handle on the
      anchor. */
  get kStateWaitingAnchor() {
    return 3;
  },
  /** The panel is open. */
  get kStateShown() {
    return 4;
    return 3;
  },

  /**
@@ -240,7 +231,6 @@ var DownloadsPanel = {
   */
  get isPanelShowing() {
    return this._state == this.kStateWaitingData ||
           this._state == this.kStateWaitingAnchor ||
           this._state == this.kStateShown;
  },

@@ -508,27 +498,19 @@ var DownloadsPanel = {
      return;
    }

    this._state = this.kStateWaitingAnchor;

    // Ensure the anchor is visible.  If that is not possible, show the panel
    // anchored to the top area of the window, near the default anchor position.
    DownloadsButton.getAnchor(anchor => {
      // If somehow we've switched states already (by getting a panel hiding
      // event before an overlay is loaded, for example), bail out.
      if (this._state != this.kStateWaitingAnchor) {
        return;
      }

    // At this point, if the window is minimized, opening the panel could fail
    // without any notification, and there would be no way to either open or
    // close the panel any more.  To prevent this, check if the window is
    // minimized and in that case force the panel to the closed state.
    if (window.windowState == window.STATE_MINIMIZED) {
        DownloadsButton.releaseAnchor();
      this._state = this.kStateHidden;
      return;
    }

    // Ensure the anchor is visible.  If that is not possible, show the panel
    // anchored to the top area of the window, near the default anchor position.
    let anchor = DownloadsButton.getAnchor();

    if (!anchor) {
      DownloadsCommon.error("Downloads button cannot be found.");
      return;
@@ -548,91 +530,11 @@ var DownloadsPanel = {
    DownloadsCommon.log("Opening downloads panel popup.");
    PanelMultiView.openPopup(this.panel, anchor, "bottomcenter topright",
                             0, 0, false, null).catch(Cu.reportError);
    });
  },
};

XPCOMUtils.defineConstant(this, "DownloadsPanel", DownloadsPanel);

// DownloadsOverlayLoader

/**
 * Allows loading the downloads panel and the status indicator interfaces on
 * demand, to improve startup performance.
 */
var DownloadsOverlayLoader = {
  /**
   * We cannot load two overlays at the same time, thus we use a queue of
   * pending load requests.
   */
  _loadRequests: [],

  /**
   * True while we are waiting for an overlay to be loaded.
   */
  _overlayLoading: false,

  /**
   * This object has a key for each overlay URI that is already loaded.
   */
  _loadedOverlays: {},

  /**
   * Loads the specified overlay and invokes the given callback when finished.
   *
   * @param aOverlay
   *        String containing the URI of the overlay to load in the current
   *        window.  If this overlay has already been loaded using this
   *        function, then the overlay is not loaded again.
   * @param aCallback
   *        Invoked when loading is completed.  If the overlay is already
   *        loaded, the function is called immediately.
   */
  ensureOverlayLoaded(aOverlay, aCallback) {
    // The overlay is already loaded, invoke the callback immediately.
    if (aOverlay in this._loadedOverlays) {
      aCallback();
      return;
    }

    // The callback will be invoked when loading is finished.
    this._loadRequests.push({ overlay: aOverlay, callback: aCallback });
    if (this._overlayLoading) {
      return;
    }

    this._overlayLoading = true;
    DownloadsCommon.log("Loading overlay ", aOverlay);
    document.loadOverlay(aOverlay, () => {
      this._overlayLoading = false;
      this._loadedOverlays[aOverlay] = true;

      this.processPendingRequests();
    });
  },

  /**
   * Re-processes all the currently pending requests, invoking the callbacks
   * and/or loading more overlays as needed.  In most cases, there will be a
   * single request for one overlay, that will be processed immediately.
   */
  processPendingRequests() {
    // Re-process all the currently pending requests, yet allow more requests
    // to be appended at the end of the array if we're not ready for them.
    let currentLength = this._loadRequests.length;
    for (let i = 0; i < currentLength; i++) {
      let request = this._loadRequests.shift();

      // We must call ensureOverlayLoaded again for each request, to check if
      // the associated callback can be invoked now, or if we must still wait
      // for the associated overlay to load.
      this.ensureOverlayLoaded(request.overlay, request.callback);
    }
  },
};

XPCOMUtils.defineConstant(this, "DownloadsOverlayLoader", DownloadsOverlayLoader);

// DownloadsView

/**
+17 −42
Original line number Diff line number Diff line
@@ -39,13 +39,6 @@ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 * downloads panel.
 */
const DownloadsButton = {
  /**
   * Location of the indicator overlay.
   */
  get kIndicatorOverlay() {
    return "chrome://browser/content/downloads/indicatorOverlay.xul";
  },

  /**
   * Returns a reference to the downloads button position placeholder, or null
   * if not available because it has been removed from the toolbars.
@@ -78,8 +71,7 @@ const DownloadsButton = {
  _getAnchorInternal() {
    let indicator = DownloadsIndicatorView.indicator;
    if (!indicator) {
      // Exit now if the indicator overlay isn't loaded yet, or if the button
      // is not in the document.
      // Exit now if the button is not in the document.
      return null;
    }

@@ -104,22 +96,18 @@ const DownloadsButton = {
  /**
   * Ensures that there is an anchor available for the panel.
   *
   * @param aCallback
   *        Called when the anchor is available, passing the element where the
   *        panel should be anchored, or null if an anchor is not available (for
   *        example because both the tab bar and the navigation bar are hidden).
   * @return Anchor element where the panel should be anchored, or null if an
   *         anchor is not available (for example because both the tab bar and
   *         the navigation bar are hidden).
   */
  getAnchor(aCallback) {
  getAnchor() {
    // Do not allow anchoring the panel to the element while customizing.
    if (this._customizing) {
      aCallback(null);
      return;
      return null;
    }

    DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => {
    this._anchorRequested = true;
      aCallback(this._getAnchorInternal());
    });
    return this._getAnchorInternal();
  },

  /**
@@ -300,39 +288,26 @@ const DownloadsIndicatorView = {

  /**
   * Ensures that the user interface elements required to display the indicator
   * are loaded, then invokes the given callback.
   * are loaded.
   */
  _ensureOperational(aCallback) {
  _ensureOperational() {
    if (this._operational) {
      if (aCallback) {
        aCallback();
      }
      return;
    }

    // If we don't have a _placeholder, there's no chance that the overlay
    // If we don't have a _placeholder, there's no chance that everything
    // will load correctly: bail (and don't set _operational to true!)
    if (!DownloadsButton._placeholder) {
      return;
    }

    DownloadsOverlayLoader.ensureOverlayLoaded(
      DownloadsButton.kIndicatorOverlay,
      () => {
    this._operational = true;

    // If the view is initialized, we need to update the elements now that
    // they are finally available in the document.
        // We need to re-check for the placeholder because it might have
        // disappeared since then.
        if (this._initialized && DownloadsButton._placeholder) {
    if (this._initialized) {
      DownloadsCommon.getIndicatorData(window).refreshView(this);
    }

        if (aCallback) {
          aCallback();
        }
      });
  },

  // Direct control functions
+0 −34
Original line number Diff line number Diff line
<?xml version="1.0"?>
<!-- -*- Mode: HTML; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- -->
<!-- vim: set ts=2 et sw=2 tw=80: -->

<!-- This Source Code Form is subject to the terms of the Mozilla Public
   - License, v. 2.0. If a copy of the MPL was not distributed with this file,
   - You can obtain one at http://mozilla.org/MPL/2.0/. -->

<!DOCTYPE overlay [
  <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
  %browserDTD;
]>

<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="indicatorOverlay">

  <!-- We dynamically add the stack with the progress meter and notification icon,
       originally loaded lazily because of performance reasons, to the existing
       downloads-button. -->
  <toolbarbutton id="downloads-button" indicator="true">
    <!-- The panel's anchor area is smaller than the outer button, but must
         always be visible and must not move or resize when the indicator
         state changes, otherwise the panel could change its position or lose
         its arrow unexpectedly. -->
    <stack id="downloads-indicator-anchor"
           consumeanchor="downloads-button">
      <box id="downloads-indicator-icon"/>
      <stack id="downloads-indicator-progress-outer">
        <box id="downloads-indicator-progress-inner"/>
      </stack>
    </stack>
  </toolbarbutton>
</overlay>
+0 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ browser.jar:
        content/browser/downloads/downloads.css          (content/downloads.css)
        content/browser/downloads/downloads.js           (content/downloads.js)
        content/browser/downloads/indicator.js           (content/indicator.js)
        content/browser/downloads/indicatorOverlay.xul   (content/indicatorOverlay.xul)
*       content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul)
        content/browser/downloads/allDownloadsViewOverlay.js  (content/allDownloadsViewOverlay.js)
*       content/browser/downloads/contentAreaDownloadsView.xul (content/contentAreaDownloadsView.xul)