browser/components/downloads/src/DownloadsTaskbar.jsm

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /**
     8  * Handles the download progress indicator in the taskbar.
     9  */
    11 "use strict";
    13 this.EXPORTED_SYMBOLS = [
    14   "DownloadsTaskbar",
    15 ];
    17 ////////////////////////////////////////////////////////////////////////////////
    18 //// Globals
    20 const Cc = Components.classes;
    21 const Ci = Components.interfaces;
    22 const Cu = Components.utils;
    23 const Cr = Components.results;
    25 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    27 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
    28                                   "resource://gre/modules/Downloads.jsm");
    29 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
    30                                   "resource:///modules/RecentWindow.jsm");
    31 XPCOMUtils.defineLazyModuleGetter(this, "Services",
    32                                   "resource://gre/modules/Services.jsm");
    34 XPCOMUtils.defineLazyGetter(this, "gWinTaskbar", function () {
    35   if (!("@mozilla.org/windows-taskbar;1" in Cc)) {
    36     return null;
    37   }
    38   let winTaskbar = Cc["@mozilla.org/windows-taskbar;1"]
    39                      .getService(Ci.nsIWinTaskbar);
    40   return winTaskbar.available && winTaskbar;
    41 });
    43 XPCOMUtils.defineLazyGetter(this, "gMacTaskbarProgress", function () {
    44   return ("@mozilla.org/widget/macdocksupport;1" in Cc) &&
    45          Cc["@mozilla.org/widget/macdocksupport;1"]
    46            .getService(Ci.nsITaskbarProgress);
    47 });
    49 ////////////////////////////////////////////////////////////////////////////////
    50 //// DownloadsTaskbar
    52 /**
    53  * Handles the download progress indicator in the taskbar.
    54  */
    55 this.DownloadsTaskbar = {
    56   /**
    57    * Underlying DownloadSummary providing the aggregate download information, or
    58    * null if the indicator has never been initialized.
    59    */
    60   _summary: null,
    62   /**
    63    * nsITaskbarProgress object to which download information is dispatched.
    64    * This can be null if the indicator has never been initialized or if the
    65    * indicator is currently hidden on Windows.
    66    */
    67   _taskbarProgress: null,
    69   /**
    70    * This method is called after a new browser window is opened, and ensures
    71    * that the download progress indicator is displayed in the taskbar.
    72    *
    73    * On Windows, the indicator is attached to the first browser window that
    74    * calls this method.  When the window is closed, the indicator is moved to
    75    * another browser window, if available, in no particular order.  When there
    76    * are no browser windows visible, the indicator is hidden.
    77    *
    78    * On Mac OS X, the indicator is initialized globally when this method is
    79    * called for the first time.  Subsequent calls have no effect.
    80    *
    81    * @param aBrowserWindow
    82    *        nsIDOMWindow object of the newly opened browser window to which the
    83    *        indicator may be attached.
    84    */
    85   registerIndicator: function (aBrowserWindow)
    86   {
    87     if (!this._taskbarProgress) {
    88       if (gMacTaskbarProgress) {
    89         // On Mac OS X, we have to register the global indicator only once.
    90         this._taskbarProgress = gMacTaskbarProgress;
    91         // Free the XPCOM reference on shutdown, to prevent detecting a leak.
    92         Services.obs.addObserver(() => {
    93           this._taskbarProgress = null;
    94           gMacTaskbarProgress = null;
    95         }, "quit-application-granted", false);
    96       } else if (gWinTaskbar) {
    97         // On Windows, the indicator is currently hidden because we have no
    98         // previous browser window, thus we should attach the indicator now.
    99         this._attachIndicator(aBrowserWindow);
   100       } else {
   101         // The taskbar indicator is not available on this platform.
   102         return;
   103       }
   104     }
   106     // Ensure that the DownloadSummary object will be created asynchronously.
   107     if (!this._summary) {
   108       Downloads.getSummary(Downloads.ALL).then(summary => {
   109         // In case the method is re-entered, we simply ignore redundant
   110         // invocations of the callback, instead of keeping separate state.
   111         if (this._summary) {
   112           return;
   113         }
   114         this._summary = summary;
   115         return this._summary.addView(this);
   116       }).then(null, Cu.reportError);
   117     }
   118   },
   120   /**
   121    * On Windows, attaches the taskbar indicator to the specified browser window.
   122    */
   123   _attachIndicator: function (aWindow)
   124   {
   125     // Activate the indicator on the specified window.
   126     let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
   127                           .getInterface(Ci.nsIWebNavigation)
   128                           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
   129                           .QueryInterface(Ci.nsIInterfaceRequestor)
   130                           .getInterface(Ci.nsIXULWindow).docShell;
   131     this._taskbarProgress = gWinTaskbar.getTaskbarProgress(docShell);
   133     // If the DownloadSummary object has already been created, we should update
   134     // the state of the new indicator, otherwise it will be updated as soon as
   135     // the DownloadSummary view is registered.
   136     if (this._summary) {
   137       this.onSummaryChanged();
   138     }
   140     aWindow.addEventListener("unload", () => {
   141       // Locate another browser window, excluding the one being closed.
   142       let browserWindow = RecentWindow.getMostRecentBrowserWindow();
   143       if (browserWindow) {
   144         // Move the progress indicator to the other browser window.
   145         this._attachIndicator(browserWindow);
   146       } else {
   147         // The last browser window has been closed.  We remove the reference to
   148         // the taskbar progress object so that the indicator will be registered
   149         // again on the next browser window that is opened.
   150         this._taskbarProgress = null;
   151       }
   152     }, false);
   153   },
   155   //////////////////////////////////////////////////////////////////////////////
   156   //// DownloadSummary view
   158   onSummaryChanged: function ()
   159   {
   160     // If the last browser window has been closed, we have no indicator anymore.
   161     if (!this._taskbarProgress) {
   162       return;
   163     }
   165     if (this._summary.allHaveStopped || this._summary.progressTotalBytes == 0) {
   166       this._taskbarProgress.setProgressState(
   167                                Ci.nsITaskbarProgress.STATE_NO_PROGRESS, 0, 0);
   168     } else {
   169       // For a brief moment before completion, some download components may
   170       // report more transferred bytes than the total number of bytes.  Thus,
   171       // ensure that we never break the expectations of the progress indicator.
   172       let progressCurrentBytes = Math.min(this._summary.progressTotalBytes,
   173                                           this._summary.progressCurrentBytes);
   174       this._taskbarProgress.setProgressState(
   175                                Ci.nsITaskbarProgress.STATE_NORMAL,
   176                                progressCurrentBytes,
   177                                this._summary.progressTotalBytes);
   178     }
   179   },
   180 };

mercurial