Skip to content

Commit

Permalink
Bug 548763 - Show download progress in OS X app dock icon. r=dao r=josh
Browse files Browse the repository at this point in the history
  • Loading branch information
vasi committed Mar 3, 2013
1 parent 3afaa62 commit 195d483
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 81 deletions.
11 changes: 3 additions & 8 deletions browser/base/content/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1486,14 +1486,9 @@ var gBrowserInit = {
// downloads will start right away, and getting the service again won't hurt.
setTimeout(function() {
Services.downloads;

#ifdef XP_WIN
if (Win7Features) {
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onBrowserWindowLoad(window);
}
#endif
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onBrowserWindowLoad(window);
}, 10000);

// The object handling the downloads indicator is also initialized here in the
Expand Down
69 changes: 49 additions & 20 deletions toolkit/mozapps/downloads/DownloadTaskbarProgress.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ this.EXPORTED_SYMBOLS = [
const Cc = Components.classes;
const Ci = Components.interfaces;

const kTaskbarID = "@mozilla.org/windows-taskbar;1";
const kTaskbarIDWin = "@mozilla.org/windows-taskbar;1";
const kTaskbarIDMac = "@mozilla.org/widget/macdocksupport;1";

////////////////////////////////////////////////////////////////////////////////
//// DownloadTaskbarProgress Object

this.DownloadTaskbarProgress =
{
init: function DTP_init()
{
if (DownloadTaskbarProgressUpdater) {
DownloadTaskbarProgressUpdater._init();
}
},

/**
* Called when a browser window appears. This has an effect only when we
* don't already have an active window.
Expand All @@ -31,6 +39,7 @@ this.DownloadTaskbarProgress =
*/
onBrowserWindowLoad: function DTP_onBrowserWindowLoad(aWindow)
{
this.init();
if (!DownloadTaskbarProgressUpdater) {
return;
}
Expand Down Expand Up @@ -83,6 +92,9 @@ this.DownloadTaskbarProgress =

var DownloadTaskbarProgressUpdater =
{
/// Whether the taskbar is initialized.
_initialized: false,

/// Reference to the taskbar.
_taskbar: null,

Expand All @@ -94,19 +106,28 @@ var DownloadTaskbarProgressUpdater =
*/
_init: function DTPU_init()
{
if (!(kTaskbarID in Cc)) {
// This means that the component isn't available
DownloadTaskbarProgressUpdater = null;
return;
if (this._initialized) {
return; // Already initialized
}

this._taskbar = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
if (!this._taskbar.available) {
// The Windows version is probably too old
this._initialized = true;

if (kTaskbarIDWin in Cc) {
this._taskbar = Cc[kTaskbarIDWin].getService(Ci.nsIWinTaskbar);
if (!this._taskbar.available) {
// The Windows version is probably too old
DownloadTaskbarProgressUpdater = null;
return;
}
} else if (kTaskbarIDMac in Cc) {
this._activeTaskbarProgress = Cc[kTaskbarIDMac].
getService(Ci.nsITaskbarProgress);
} else {
DownloadTaskbarProgressUpdater = null;
return;
}

this._taskbarState = Ci.nsITaskbarProgress.STATE_NO_PROGRESS;

this._dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
this._dm.addPrivacyAwareListener(this);
Expand All @@ -126,6 +147,8 @@ var DownloadTaskbarProgressUpdater =
_uninit: function DTPU_uninit() {
this._dm.removeListener(this);
this._os.removeObserver(this, "quit-application-granted");
this._activeTaskbarProgress = null;
this._initialized = false;
},

/**
Expand All @@ -150,6 +173,7 @@ var DownloadTaskbarProgressUpdater =
*/
_setActiveWindow: function DTPU_setActiveWindow(aWindow, aIsDownloadWindow)
{
#ifdef XP_WIN
// Clear out the taskbar for the old active window. (If there was no active
// window, this is a no-op.)
this._clearTaskbar();
Expand All @@ -175,13 +199,27 @@ var DownloadTaskbarProgressUpdater =
else {
this._activeTaskbarProgress = null;
}
#endif
},

/// Current state displayed on the active window's taskbar item
_taskbarState: Ci.nsITaskbarProgress.STATE_NO_PROGRESS,
_taskbarState: null,
_totalSize: 0,
_totalTransferred: 0,

// If the active window is not the download manager window, set the state
// only if it is normal or indeterminate.
_shouldSetState: function DTPU_shouldSetState()
{
#ifdef XP_WIN
return this._activeWindowIsDownloadWindow ||
(this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL ||
this._taskbarState == Ci.nsITaskbarProgress.STATE_INDETERMINATE);
#else
return true;
#endif
},

/**
* Update the active window's taskbar indicator with the current state. There
* are two cases here:
Expand All @@ -198,11 +236,7 @@ var DownloadTaskbarProgressUpdater =
return;
}

// If the active window is not the download manager window, set the state
// only if it is normal or indeterminate.
if (this._activeWindowIsDownloadWindow ||
(this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL ||
this._taskbarState == Ci.nsITaskbarProgress.STATE_INDETERMINATE)) {
if (this._shouldSetState()) {
this._activeTaskbarProgress.setProgressState(this._taskbarState,
this._totalTransferred,
this._totalSize);
Expand Down Expand Up @@ -361,8 +395,3 @@ var DownloadTaskbarProgressUpdater =
}
}
};

////////////////////////////////////////////////////////////////////////////////
//// Initialization

DownloadTaskbarProgressUpdater._init();
6 changes: 1 addition & 5 deletions toolkit/mozapps/downloads/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ EXTRA_JS_MODULES = \
DownloadUtils.jsm \
$(NULL)

ifeq ($(OS_ARCH),WINNT)
EXTRA_JS_MODULES += \
DownloadTaskbarProgress.jsm \
$(NULL)
endif
EXTRA_PP_JS_MODULES = DownloadTaskbarProgress.jsm

include $(topsrcdir)/config/rules.mk
8 changes: 3 additions & 5 deletions toolkit/mozapps/downloads/content/downloads.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,9 @@ function Startup()
}
}, false);

#ifdef XP_WIN
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", tempScope);
tempScope.DownloadTaskbarProgress.onDownloadWindowLoad(window);
#endif
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onDownloadWindowLoad(window);
}

function Shutdown()
Expand Down
6 changes: 5 additions & 1 deletion toolkit/mozapps/downloads/tests/chrome/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ MOCHITEST_CHROME_FILES += \
$(NULL)
endif

ifeq ($(OS_ARCH),WINNT)
ifneq (,$(filter WINNT, $(OS_ARCH))$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
MOCHITEST_CHROME_FILES += \
test_taskbarprogress_downloadstates.xul \
$(NULL)
endif
ifeq ($(OS_ARCH),WINNT)
MOCHITEST_CHROME_FILES += \
$(filter disabled-for-very-frequent-orange--bug-630567, test_taskbarprogress_service.xul) \
$(NULL)
endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,28 +166,34 @@ function testSetup()
return;
}
let isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
if (!isWin7OrHigher) {
ok(true, "This test only runs on Windows 7 or higher");
return;
let isWin = /Win/.test(navigator.platform);
if (isWin) {
let isWin7OrHigher = false;
try {
let version = Cc["@mozilla.org/system-info;1"]
.getService(Ci.nsIPropertyBag2)
.getProperty("version");
isWin7OrHigher = (parseFloat(version) >= 6.1);
} catch (ex) { }
if (!isWin7OrHigher) {
ok(true, "This test only runs on Windows 7 or higher");
return;
}
}
let tempScope = {};
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", tempScope);
Cu.import("resource://gre/modules/Services.jsm");
DownloadTaskbarProgress = tempScope.DownloadTaskbarProgress;
let TaskbarService = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
isnot(DownloadTaskbarProgress, null, "Download taskbar progress service exists");
is(TaskbarService.available, true, "Taskbar Service is available");
DownloadTaskbarProgress.init();
if (isWin) {
let TaskbarService = Cc[kTaskbarID].getService(Ci.nsIWinTaskbar);
is(TaskbarService.available, true, "Taskbar Service is available");
}
dm = Cc["@mozilla.org/download-manager;1"].
getService(Ci.nsIDownloadManager);
Expand Down
1 change: 1 addition & 0 deletions widget/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
XPIDLSRCS += nsIMacDockSupport.idl \
nsIStandaloneNativeMenu.idl \
nsIMacWebAppUtils.idl \
nsITaskbarProgress.idl \
$(NULL)
endif

Expand Down
25 changes: 21 additions & 4 deletions widget/cocoa/nsMacDockSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,38 @@
* 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/. */

#import <Carbon/Carbon.h>

#include "nsIMacDockSupport.h"
#include "nsIStandaloneNativeMenu.h"
#include "nsITaskbarProgress.h"
#include "nsITimer.h"
#include "nsCOMPtr.h"
#include "nsString.h"

class nsMacDockSupport : public nsIMacDockSupport
class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress
{
public:
nsMacDockSupport() {}
virtual ~nsMacDockSupport() {}
nsMacDockSupport();
virtual ~nsMacDockSupport();

NS_DECL_ISUPPORTS
NS_DECL_NSIMACDOCKSUPPORT
NS_DECL_NSITASKBARPROGRESS

protected:
nsCOMPtr<nsIStandaloneNativeMenu> mDockMenu;
nsString mBadgeText;

NSImage *mAppIcon, *mProgressBackground;
HIThemeTrackDrawInfo mProgressDrawInfo;

nsTaskbarProgressState mProgressState;
double mProgressFraction;
nsCOMPtr<nsITimer> mProgressTimer;

static void RedrawIconCallback(nsITimer* aTimer, void* aClosure);

bool InitProgress();
nsresult RedrawIcon();
};
Loading

0 comments on commit 195d483

Please sign in to comment.