Bug 801232 - Add support for the downloads panel in per-window private browsing builds; r=mak

This commit is contained in:
Ehsan Akhgari 2012-12-05 22:31:26 -05:00
parent 45d35b7949
commit 2f2d76a5a5
8 changed files with 255 additions and 86 deletions

View File

@ -44,6 +44,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
"resource:///modules/DownloadsCommon.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
////////////////////////////////////////////////////////////////////////////////
//// DownloadsPanel
@ -107,7 +109,7 @@ const DownloadsPanel = {
DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
function DP_I_callback() {
DownloadsViewController.initialize();
DownloadsCommon.data.addView(DownloadsView);
DownloadsCommon.getData(window).addView(DownloadsView);
DownloadsPanel._attachEventListeners();
aCallback();
});
@ -130,7 +132,7 @@ const DownloadsPanel = {
this.hidePanel();
DownloadsViewController.terminate();
DownloadsCommon.data.removeView(DownloadsView);
DownloadsCommon.getData(window).removeView(DownloadsView);
this._unattachEventListeners();
this._state = this.kStateUninitialized;
@ -230,7 +232,7 @@ const DownloadsPanel = {
this._state = this.kStateShown;
// Since at most one popup is open at any given time, we can set globally.
DownloadsCommon.indicatorData.attentionSuppressed = true;
DownloadsCommon.getIndicatorData(window).attentionSuppressed = true;
// Ensure that an item is selected when the panel is focused.
if (DownloadsView.richListBox.itemCount > 0 &&
@ -249,7 +251,7 @@ const DownloadsPanel = {
}
// Since at most one popup is open at any given time, we can set globally.
DownloadsCommon.indicatorData.attentionSuppressed = false;
DownloadsCommon.getIndicatorData(window).attentionSuppressed = false;
// Allow the anchor to be hidden.
DownloadsButton.releaseAnchor();
@ -1110,7 +1112,11 @@ const DownloadsViewController = {
{
// Handle commands that are not selection-specific.
if (aCommand == "downloadsCmd_clearList") {
return Services.downloads.canCleanUp;
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
return Services.downloads.canCleanUpPrivate;
} else {
return Services.downloads.canCleanUp;
}
}
// Other commands are selection-specific.
@ -1157,7 +1163,11 @@ const DownloadsViewController = {
commands: {
downloadsCmd_clearList: function DVC_downloadsCmd_clearList()
{
Services.downloads.cleanUp();
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
Services.downloads.cleanUpPrivate();
} else {
Services.downloads.cleanUp();
}
}
}
};
@ -1171,7 +1181,7 @@ const DownloadsViewController = {
*/
function DownloadsViewItemController(aElement) {
let downloadGuid = aElement.getAttribute("downloadGuid");
this.dataItem = DownloadsCommon.data.dataItems[downloadGuid];
this.dataItem = DownloadsCommon.getData(window).dataItems[downloadGuid];
}
DownloadsViewItemController.prototype = {
@ -1457,10 +1467,10 @@ const DownloadsSummary = {
return this._active;
}
if (aActive) {
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
.addView(this);
} else {
DownloadsCommon.getSummary(DownloadsView.kItemCountLimit)
DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit)
.removeView(this);
DownloadsFooter.showingSummary = false;
}

View File

@ -286,7 +286,7 @@ const DownloadsIndicatorView = {
this._initialized = true;
window.addEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.addView(this);
DownloadsCommon.getIndicatorData(window).addView(this);
},
/**
@ -300,7 +300,7 @@ const DownloadsIndicatorView = {
this._initialized = false;
window.removeEventListener("unload", this.onWindowUnload, false);
DownloadsCommon.indicatorData.removeView(this);
DownloadsCommon.getIndicatorData(window).removeView(this);
// Reset the view properties, so that a neutral indicator is displayed if we
// are visible only temporarily as an anchor.
@ -327,7 +327,7 @@ const DownloadsIndicatorView = {
// If the view is initialized, we need to update the elements now that
// they are finally available in the document.
if (this._initialized) {
DownloadsCommon.indicatorData.refreshView(this);
DownloadsCommon.getIndicatorData(window).refreshView(this);
}
aCallback();
@ -508,7 +508,7 @@ const DownloadsIndicatorView = {
{
if (DownloadsCommon.useToolkitUI) {
// The panel won't suppress attention for us, we need to clear now.
DownloadsCommon.indicatorData.attention = false;
DownloadsCommon.getIndicatorData(window).attention = false;
BrowserDownloadsUI();
} else {
DownloadsPanel.showPanel();

View File

@ -56,6 +56,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
"resource:///modules/RecentWindow.jsm");
const nsIDM = Ci.nsIDownloadManager;
@ -173,37 +177,95 @@ this.DownloadsCommon = {
},
/**
* Returns a reference to the DownloadsData singleton.
* Get access to one of the DownloadsData or PrivateDownloadsData objects,
* depending on the privacy status of the window in question.
*
* This does not need to be a lazy getter, since no initialization is required
* at present.
* @param aWindow
* The browser window which owns the download button.
*/
get data() DownloadsData,
getData: function DC_getData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsData;
} else {
return DownloadsData;
}
},
/**
* Returns a reference to the DownloadsData singleton.
* Initializes the data link for both the private and non-private downloads
* data objects.
*
* This does not need to be a lazy getter, since no initialization is required
* at present.
* @param aDownloadManagerService
* Reference to the service implementing nsIDownloadManager. We need
* this because getService isn't available for us when this method is
* called, and we must ensure to register our listeners before the
* getService call for the Download Manager returns.
*/
get indicatorData() DownloadsIndicatorData,
initializeAllDataLinks: function DC_initializeAllDataLinks(aDownloadManagerService) {
DownloadsData.initializeDataLink(aDownloadManagerService);
PrivateDownloadsData.initializeDataLink(aDownloadManagerService);
},
/**
* Terminates the data link for both the private and non-private downloads
* data objects.
*/
terminateAllDataLinks: function DC_terminateAllDataLinks() {
DownloadsData.terminateDataLink();
PrivateDownloadsData.terminateDataLink();
},
/**
* Reloads the specified kind of downloads from the non-private store.
* This method must only be called when Private Browsing Mode is disabled.
*
* @param aActiveOnly
* True to load only active downloads from the database.
*/
ensureAllPersistentDataLoaded:
function DC_ensureAllPersistentDataLoaded(aActiveOnly) {
DownloadsData.ensurePersistentDataLoaded(aActiveOnly);
},
/**
* Get access to one of the DownloadsIndicatorData or
* PrivateDownloadsIndicatorData objects, depending on the privacy status of
* the window in question.
*/
getIndicatorData: function DC_getIndicatorData(aWindow) {
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
return PrivateDownloadsIndicatorData;
} else {
return DownloadsIndicatorData;
}
},
/**
* Returns a reference to the DownloadsSummaryData singleton - creating one
* in the process if one hasn't been instantiated yet.
*
* @param aWindow
* The browser window which owns the download button.
* @param aNumToExclude
* The number of items on the top of the downloads list to exclude
* from the summary.
*/
_summary: null,
getSummary: function DC_getSummary(aNumToExclude)
getSummary: function DC_getSummary(aWindow, aNumToExclude)
{
if (this._summary) {
return this._summary;
if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) {
if (this._privateSummary) {
return this._privateSummary;
}
return this._privateSummary = new DownloadsSummaryData(true, aNumToExclude);
} else {
if (this._summary) {
return this._summary;
}
return this._summary = new DownloadsSummaryData(false, aNumToExclude);
}
return this._summary = new DownloadsSummaryData(aNumToExclude);
},
_summary: null,
_privateSummary: null,
/**
* Given an iterable collection of DownloadDataItems, generates and returns
@ -354,8 +416,33 @@ XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
* service. Consumers will see an empty list of downloads until the service is
* actually started. This is useful to display a neutral progress indicator in
* the main browser window until the autostart timeout elapses.
*
* Note that DownloadsData and PrivateDownloadsData are two equivalent singleton
* objects, one accessing non-private downloads, and the other accessing private
* ones.
*/
const DownloadsData = {
function DownloadsDataCtor(aPrivate) {
this._isPrivate = aPrivate;
// This Object contains all the available DownloadsDataItem objects, indexed by
// their globally unique identifier. The identifiers of downloads that have
// been removed from the Download Manager data are still present, however the
// associated objects are replaced with the value "null". This is required to
// prevent race conditions when populating the list asynchronously.
this.dataItems = {};
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
// While operating in Private Browsing Mode, persistent data items are parked
// here until we return to the normal mode.
this._persistentDataItems = {};
#endif
// Array of view objects that should be notified when the available download
// data changes.
this._views = [];
}
DownloadsDataCtor.prototype = {
/**
* Starts receiving events for current downloads.
*
@ -368,10 +455,12 @@ const DownloadsData = {
initializeDataLink: function DD_initializeDataLink(aDownloadManagerService)
{
// Start receiving real-time events.
aDownloadManagerService.addListener(this);
aDownloadManagerService.addPrivacyAwareListener(this);
Services.obs.addObserver(this, "download-manager-remove-download-guid", false);
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.addObserver(this, "download-manager-database-type-changed",
false);
#endif
},
/**
@ -382,7 +471,9 @@ const DownloadsData = {
this._terminateDataAccess();
// Stop receiving real-time events.
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
Services.obs.removeObserver(this, "download-manager-database-type-changed");
#endif
Services.obs.removeObserver(this, "download-manager-remove-download-guid");
Services.downloads.removeListener(this);
},
@ -390,12 +481,6 @@ const DownloadsData = {
//////////////////////////////////////////////////////////////////////////////
//// Registration of views
/**
* Array of view objects that should be notified when the available download
* data changes.
*/
_views: [],
/**
* Adds an object to be notified when the available download data changes.
* The specified object is initialized with the currently available downloads.
@ -454,21 +539,6 @@ const DownloadsData = {
//////////////////////////////////////////////////////////////////////////////
//// In-memory downloads data store
/**
* Object containing all the available DownloadsDataItem objects, indexed by
* their numeric download identifier. The identifiers of downloads that have
* been removed from the Download Manager data are still present, however the
* associated objects are replaced with the value "null". This is required to
* prevent race conditions when populating the list asynchronously.
*/
dataItems: {},
/**
* While operating in Private Browsing Mode, persistent data items are parked
* here until we return to the normal mode.
*/
_persistentDataItems: {},
/**
* Clears the loaded data.
*/
@ -591,7 +661,9 @@ const DownloadsData = {
// Reload the list using the Download Manager service. The list is
// returned in no particular order.
let downloads = Services.downloads.activeDownloads;
let downloads = this._isPrivate ?
Services.downloads.activePrivateDownloads :
Services.downloads.activeDownloads;
while (downloads.hasMoreElements()) {
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
this._getOrAddDataItem(download, true);
@ -609,7 +681,10 @@ const DownloadsData = {
// columns are read in the _initFromDataRow method of DownloadsDataItem.
// Order by descending download identifier so that the most recent
// downloads are notified first to the listening views.
let statement = Services.downloads.DBConnection.createAsyncStatement(
let dbConnection = this._isPrivate ?
Services.downloads.privateDBConnection :
Services.downloads.DBConnection;
let statement = dbConnection.createAsyncStatement(
"SELECT guid, target, name, source, referrer, state, "
+ "startTime, endTime, currBytes, maxBytes "
+ "FROM moz_downloads "
@ -714,6 +789,7 @@ const DownloadsData = {
}
break;
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "download-manager-database-type-changed":
let pbs = Cc["@mozilla.org/privatebrowsing;1"]
.getService(Ci.nsIPrivateBrowsingService);
@ -731,6 +807,7 @@ const DownloadsData = {
// already invalidated by the previous calls.
this._views.forEach(this._updateView, this);
break;
#endif
}
},
@ -739,6 +816,12 @@ const DownloadsData = {
onDownloadStateChange: function DD_onDownloadStateChange(aState, aDownload)
{
if (aDownload.isPrivate != this._isPrivate) {
// Ignore the downloads with a privacy status other than what we are
// tracking.
return;
}
// When a new download is added, it may have the same identifier of a
// download that we previously deleted during this session, and we also
// want to provide a visible indication that the download started.
@ -784,6 +867,12 @@ const DownloadsData = {
aCurTotalProgress,
aMaxTotalProgress, aDownload)
{
if (aDownload.isPrivate != this._isPrivate) {
// Ignore the downloads with a privacy status other than what we are
// tracking.
return;
}
let dataItem = this._getOrAddDataItem(aDownload, false);
if (!dataItem) {
return;
@ -833,7 +922,7 @@ const DownloadsData = {
}
// Show the panel in the most recent browser window, if present.
let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate });
if (!browserWin) {
return;
}
@ -850,6 +939,14 @@ const DownloadsData = {
}
};
XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsData", function() {
return new DownloadsDataCtor(true);
});
XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
return new DownloadsDataCtor(false);
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsDataItem
@ -1116,8 +1213,18 @@ const DownloadsViewPrototype = {
/**
* Array of view objects that should be notified when the available status
* data changes.
*
* SUBCLASSES MUST OVERRIDE THIS PROPERTY.
*/
_views: [],
_views: null,
/**
* Determines whether this view object is over the private or non-private
* downloads.
*
* SUBCLASSES MUST OVERRIDE THIS PROPERTY.
*/
_isPrivate: false,
/**
* Adds an object to be notified when the available status data changes.
@ -1131,7 +1238,11 @@ const DownloadsViewPrototype = {
{
// Start receiving events when the first of our views is registered.
if (this._views.length == 0) {
DownloadsCommon.data.addView(this);
if (this._isPrivate) {
PrivateDownloadsData.addView(this);
} else {
DownloadsData.addView(this);
}
}
this._views.push(aView);
@ -1167,7 +1278,11 @@ const DownloadsViewPrototype = {
// Stop receiving events when the last of our views is unregistered.
if (this._views.length == 0) {
DownloadsCommon.data.removeView(this);
if (this._isPrivate) {
PrivateDownloadsData.removeView(this);
} else {
DownloadsData.removeView(this);
}
}
},
@ -1291,7 +1406,10 @@ const DownloadsViewPrototype = {
* actually started. This is useful to display a neutral progress indicator in
* the main browser window until the autostart timeout elapses.
*/
const DownloadsIndicatorData = {
function DownloadsIndicatorDataCtor(aPrivate) {
this._isPrivate = aPrivate;
}
DownloadsIndicatorDataCtor.prototype = {
__proto__: DownloadsViewPrototype,
/**
@ -1373,23 +1491,25 @@ const DownloadsIndicatorData = {
*/
getViewItem: function DID_getViewItem(aDataItem)
{
let data = this._isPrivate ? PrivateDownloadsIndicatorData
: DownloadsIndicatorData;
return Object.freeze({
onStateChange: function DIVI_onStateChange()
{
if (aDataItem.state == nsIDM.DOWNLOAD_FINISHED ||
aDataItem.state == nsIDM.DOWNLOAD_FAILED) {
DownloadsIndicatorData.attention = true;
data.attention = true;
}
// Since the state of a download changed, reset the estimated time left.
DownloadsIndicatorData._lastRawTimeLeft = -1;
DownloadsIndicatorData._lastTimeLeft = -1;
data._lastRawTimeLeft = -1;
data._lastTimeLeft = -1;
DownloadsIndicatorData._updateViews();
data._updateViews();
},
onProgressChange: function DIVI_onProgressChange()
{
DownloadsIndicatorData._updateViews();
data._updateViews();
}
});
},
@ -1489,7 +1609,9 @@ const DownloadsIndicatorData = {
*/
_activeDataItems: function DID_activeDataItems()
{
for each (let dataItem in DownloadsCommon.data.dataItems) {
let dataItems = this._isPrivate ? PrivateDownloadsData.dataItems
: DownloadsData.dataItems;
for each (let dataItem in dataItems) {
if (dataItem && dataItem.inProgress) {
yield dataItem;
}
@ -1529,7 +1651,15 @@ const DownloadsIndicatorData = {
this._counter = DownloadsCommon.formatTimeLeft(this._lastTimeLeft);
}
}
}
};
XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsIndicatorData", function() {
return new DownloadsIndicatorDataCtor(true);
});
XPCOMUtils.defineLazyGetter(this, "DownloadsIndicatorData", function() {
return new DownloadsIndicatorDataCtor(false);
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsSummaryData
@ -1541,16 +1671,18 @@ const DownloadsIndicatorData = {
* constructed with aNumToExclude equal to 3, then that DownloadsSummaryData
* would produce a summary of the last 2 downloads.
*
* @param aIsPrivate
* True if the browser window which owns the download button is a private
* window.
* @param aNumToExclude
* The number of items to exclude from the summary, starting from the
* top of the list.
*/
function DownloadsSummaryData(aNumToExclude) {
function DownloadsSummaryData(aIsPrivate, aNumToExclude) {
this._numToExclude = aNumToExclude;
// Since we can have multiple instances of DownloadsSummaryData, we
// override these values from the prototype so that each instance can be
// completely separated from one another.
this._views = [];
this._loading = false;
this._dataItems = [];
@ -1574,6 +1706,9 @@ function DownloadsSummaryData(aNumToExclude) {
this._description = "";
this._numActive = 0;
this._percentComplete = -1;
this._isPrivate = aIsPrivate;
this._views = [];
}
DownloadsSummaryData.prototype = {

View File

@ -31,16 +31,22 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
"@mozilla.org/browser/sessionstartup;1",
"nsISessionStartup");
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsingService",
"@mozilla.org/privatebrowsing;1",
"nsIPrivateBrowsingService");
#endif
const kObservedTopics = [
"sessionstore-windows-restored",
"sessionstore-browser-state-restored",
"download-manager-initialized",
"download-manager-change-retention",
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
"last-pb-context-exited",
#else
"private-browsing-transition-complete",
#endif
"browser-lastwindow-close-granted",
"quit-application",
"profile-change-teardown",
@ -113,8 +119,8 @@ DownloadsStartup.prototype = {
// Start receiving events for active and new downloads before we return
// from this observer function. We can't defer the execution of this
// step, to ensure that we don't lose events raised in the meantime.
DownloadsCommon.data.initializeDataLink(
aSubject.QueryInterface(Ci.nsIDownloadManager));
DownloadsCommon.initializeAllDataLinks(
aSubject.QueryInterface(Ci.nsIDownloadManager));
this._downloadsServiceInitialized = true;
@ -139,11 +145,13 @@ DownloadsStartup.prototype = {
}
break;
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "private-browsing-transition-complete":
// Ensure that persistent data is reloaded only when the database
// connection is available again.
this._ensureDataLoaded();
break;
#endif
case "browser-lastwindow-close-granted":
// When using the panel interface, downloads that are already completed
@ -158,6 +166,16 @@ DownloadsStartup.prototype = {
}
break;
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
case "last-pb-context-exited":
// Similar to the above notification, but for private downloads.
if (this._downloadsServiceInitialized &&
!DownloadsCommon.useToolkitUI) {
Services.downloads.cleanUpPrivate();
}
break;
#endif
case "quit-application":
// When the application is shutting down, we must free all resources in
// addition to cleaning up completed downloads. If the Download Manager
@ -169,7 +187,7 @@ DownloadsStartup.prototype = {
break;
}
DownloadsCommon.data.terminateDataLink();
DownloadsCommon.terminateAllDataLinks();
// When using the panel interface, downloads that are already completed
// should be removed when quitting the application.
@ -258,15 +276,18 @@ DownloadsStartup.prototype = {
*/
_ensureDataLoaded: function DS_ensureDataLoaded()
{
if (!this._downloadsServiceInitialized ||
gPrivateBrowsingService.privateBrowsingEnabled) {
if (!this._downloadsServiceInitialized
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
|| gPrivateBrowsingService.privateBrowsingEnabled
#endif
) {
return;
}
// If the previous session has been already restored, then we ensure that
// all the downloads are loaded. Otherwise, we only ensure that the active
// downloads from the previous session are loaded.
DownloadsCommon.data.ensurePersistentDataLoaded(!this._recoverAllDownloads);
DownloadsCommon.ensureAllPersistentDataLoaded(!this._recoverAllDownloads);
}
};

View File

@ -11,11 +11,14 @@ include $(DEPTH)/config/autoconf.mk
EXTRA_COMPONENTS = \
BrowserDownloads.manifest \
DownloadsStartup.js \
DownloadsUI.js \
$(NULL)
EXTRA_JS_MODULES = \
EXTRA_PP_COMPONENTS = \
DownloadsStartup.js \
$(NULL)
EXTRA_PP_JS_MODULES = \
DownloadsCommon.jsm \
$(NULL)

View File

@ -33,13 +33,13 @@ function gen_test()
try {
// Ensure that state is reset in case previous tests didn't finish.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
// Populate the downloads database with the data required by this test.
for (let yy in gen_addDownloadRows(DownloadData)) yield;
// Open the user interface and wait for data to be fully loaded.
for (let yy in gen_openPanel()) yield;
for (let yy in gen_openPanel(DownloadsCommon.getData(window))) yield;
// Test item data and count. This also tests the ordering of the display.
let richlistbox = document.getElementById("downloadsListBox");
@ -57,6 +57,6 @@ function gen_test()
}
} finally {
// Clean up when the test finishes.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
}
}

View File

@ -12,32 +12,32 @@ function gen_test()
{
try {
// Ensure that state is reset in case previous tests didn't finish.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
// With this set to false, we should automatically open the panel
// the first time a download is started.
DownloadsCommon.data.panelHasShownBefore = false;
DownloadsCommon.getData(window).panelHasShownBefore = false;
prepareForPanelOpen();
DownloadsCommon.data._notifyNewDownload();
DownloadsCommon.getData(window)._notifyNewDownload();
yield;
// If we got here, that means the panel opened.
DownloadsPanel.hidePanel();
ok(DownloadsCommon.data.panelHasShownBefore,
ok(DownloadsCommon.getData(window).panelHasShownBefore,
"Should have recorded that the panel was opened on a download.")
// Next, make sure that if we start another download, we don't open
// the panel automatically.
panelShouldNotOpen();
DownloadsCommon.data._notifyNewDownload();
DownloadsCommon.getData(window)._notifyNewDownload();
yield waitFor(2);
} catch(e) {
ok(false, e);
} finally {
// Clean up when the test finishes.
for (let yy in gen_resetState()) yield;
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield;
}
}

View File

@ -130,7 +130,7 @@ var testRunner = {
// for (let yy in gen_example("Parameter")) yield;
//
function gen_resetState()
function gen_resetState(aData)
{
let statement = Services.downloads.DBConnection.createAsyncStatement(
"DELETE FROM moz_downloads");
@ -155,8 +155,8 @@ function gen_resetState()
Services.prefs.clearUserPref("browser.download.panel.shown");
// Ensure that the panel is closed and data is unloaded.
DownloadsCommon.data.clear();
DownloadsCommon.data._loadState = DownloadsCommon.data.kLoadNone;
aData.clear();
aData._loadState = aData.kLoadNone;
DownloadsPanel.hidePanel();
// Wait for focus on the main window.
@ -224,7 +224,7 @@ function gen_openPanel(aData)
};
// Start loading all the downloads from the database asynchronously.
DownloadsCommon.data.ensurePersistentDataLoaded(false);
aData.ensurePersistentDataLoaded(false);
// Wait for focus on the main window.
waitForFocus(testRunner.continueTest);