зеркало из https://github.com/mozilla/gecko-dev.git
Bug 899110 - Remove the code to switch between different back-ends from the Downloads Panel. r=enn
This commit is contained in:
Родитель
85da3f1250
Коммит
147dff90bb
|
@ -351,18 +351,8 @@ pref("browser.download.debug", false);
|
|||
pref("browser.download.saveLinkAsFilenameTimeout", 4000);
|
||||
|
||||
pref("browser.download.useDownloadDir", true);
|
||||
|
||||
pref("browser.download.folderList", 1);
|
||||
pref("browser.download.manager.showAlertOnComplete", true);
|
||||
pref("browser.download.manager.showAlertInterval", 2000);
|
||||
pref("browser.download.manager.retention", 2);
|
||||
pref("browser.download.manager.showWhenStarting", true);
|
||||
pref("browser.download.manager.closeWhenDone", false);
|
||||
pref("browser.download.manager.focusWhenStarting", false);
|
||||
pref("browser.download.manager.flashCount", 2);
|
||||
pref("browser.download.manager.addToRecentDocs", true);
|
||||
pref("browser.download.manager.quitBehavior", 0);
|
||||
pref("browser.download.manager.scanWhenDone", true);
|
||||
pref("browser.download.manager.resumeOnWakeDelay", 10000);
|
||||
|
||||
// This allows disabling the animated notifications shown by
|
||||
|
@ -372,10 +362,6 @@ pref("browser.download.animateNotifications", true);
|
|||
// This records whether or not the panel has been shown at least once.
|
||||
pref("browser.download.panel.shown", false);
|
||||
|
||||
// This records whether or not at least one session with the Downloads Panel
|
||||
// enabled has been completed already.
|
||||
pref("browser.download.panel.firstSessionCompleted", false);
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
pref("browser.helperApps.deleteTempFileOnExit", true);
|
||||
#endif
|
||||
|
@ -1019,10 +1005,6 @@ pref("services.sync.prefs.sync.addons.ignoreUserEnabledChanges", true);
|
|||
// source, and this would propagate automatically to other,
|
||||
// uncompromised Sync-connected devices.
|
||||
pref("services.sync.prefs.sync.app.update.mode", true);
|
||||
pref("services.sync.prefs.sync.browser.download.manager.closeWhenDone", true);
|
||||
pref("services.sync.prefs.sync.browser.download.manager.retention", true);
|
||||
pref("services.sync.prefs.sync.browser.download.manager.scanWhenDone", true);
|
||||
pref("services.sync.prefs.sync.browser.download.manager.showWhenStarting", true);
|
||||
pref("services.sync.prefs.sync.browser.formfill.enable", true);
|
||||
pref("services.sync.prefs.sync.browser.link.open_newwindow", true);
|
||||
pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
|
||||
|
|
|
@ -1084,24 +1084,13 @@ var gBrowserInit = {
|
|||
// auto-resume downloads begin (such as after crashing or quitting with
|
||||
// active downloads) and speeds up the first-load of the download manager UI.
|
||||
// If the user manually opens the download manager before the timeout, the
|
||||
// downloads will start right away, and getting the service again won't hurt.
|
||||
// downloads will start right away, and initializing again won't hurt.
|
||||
setTimeout(function() {
|
||||
try {
|
||||
let DownloadsCommon =
|
||||
Cu.import("resource:///modules/DownloadsCommon.jsm", {}).DownloadsCommon;
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
// Open the data link without initalizing nsIDownloadManager.
|
||||
DownloadsCommon.initializeAllDataLinks();
|
||||
let DownloadsTaskbar =
|
||||
Cu.import("resource:///modules/DownloadsTaskbar.jsm", {}).DownloadsTaskbar;
|
||||
DownloadsTaskbar.registerIndicator(window);
|
||||
} else {
|
||||
// Initalizing nsIDownloadManager will trigger the data link.
|
||||
Services.downloads;
|
||||
let DownloadTaskbarProgress =
|
||||
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
|
||||
DownloadTaskbarProgress.onBrowserWindowLoad(window);
|
||||
}
|
||||
Cu.import("resource:///modules/DownloadsCommon.jsm", {})
|
||||
.DownloadsCommon.initializeAllDataLinks();
|
||||
Cu.import("resource:///modules/DownloadsTaskbar.jsm", {})
|
||||
.DownloadsTaskbar.registerIndicator(window);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
|
|
@ -316,48 +316,25 @@ Sanitizer.prototype = {
|
|||
downloads: {
|
||||
clear: function ()
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
Task.spawn(function () {
|
||||
let filterByTime = null;
|
||||
if (this.range) {
|
||||
// Convert microseconds back to milliseconds for date comparisons.
|
||||
let rangeBeginMs = this.range[0] / 1000;
|
||||
let rangeEndMs = this.range[1] / 1000;
|
||||
filterByTime = download => download.startTime >= rangeBeginMs &&
|
||||
download.startTime <= rangeEndMs;
|
||||
}
|
||||
|
||||
// Clear all completed/cancelled downloads
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
list.removeFinished(filterByTime);
|
||||
}.bind(this)).then(null, Components.utils.reportError);
|
||||
}
|
||||
else {
|
||||
var dlMgr = Components.classes["@mozilla.org/download-manager;1"]
|
||||
.getService(Components.interfaces.nsIDownloadManager);
|
||||
|
||||
Task.spawn(function () {
|
||||
let filterByTime = null;
|
||||
if (this.range) {
|
||||
// First, remove the completed/cancelled downloads
|
||||
dlMgr.removeDownloadsByTimeframe(this.range[0], this.range[1]);
|
||||
// Convert microseconds back to milliseconds for date comparisons.
|
||||
let rangeBeginMs = this.range[0] / 1000;
|
||||
let rangeEndMs = this.range[1] / 1000;
|
||||
filterByTime = download => download.startTime >= rangeBeginMs &&
|
||||
download.startTime <= rangeEndMs;
|
||||
}
|
||||
else {
|
||||
// Clear all completed/cancelled downloads
|
||||
dlMgr.cleanUp();
|
||||
dlMgr.cleanUpPrivate();
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all completed/cancelled downloads
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
list.removeFinished(filterByTime);
|
||||
}.bind(this)).then(null, Components.utils.reportError);
|
||||
},
|
||||
|
||||
canClear : function(aCallback, aArg)
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
aCallback("downloads", true, aArg);
|
||||
}
|
||||
else {
|
||||
var dlMgr = Components.classes["@mozilla.org/download-manager;1"]
|
||||
.getService(Components.interfaces.nsIDownloadManager);
|
||||
aCallback("downloads", dlMgr.canCleanUp || dlMgr.canCleanUpPrivate, aArg);
|
||||
}
|
||||
aCallback("downloads", true, aArg);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -134,14 +134,9 @@ const DownloadsPanel = {
|
|||
|
||||
window.addEventListener("unload", this.onWindowUnload, false);
|
||||
|
||||
// Ensure that the Download Manager service is running. This resumes
|
||||
// active downloads if required. If there are downloads to be shown in the
|
||||
// panel, starting the service will make us load their data asynchronously.
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
DownloadsCommon.initializeAllDataLinks();
|
||||
} else {
|
||||
Services.downloads;
|
||||
}
|
||||
// Load and resume active downloads if required. If there are downloads to
|
||||
// be shown in the panel, they will be loaded asynchronously.
|
||||
DownloadsCommon.initializeAllDataLinks();
|
||||
|
||||
// Now that data loading has eventually started, load the required XUL
|
||||
// elements and initialize our views.
|
||||
|
@ -789,26 +784,6 @@ const DownloadsView = {
|
|||
DownloadsPanel.onViewLoadCompleted();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the downloads database becomes unavailable (for example,
|
||||
* entering Private Browsing Mode). References to existing data should be
|
||||
* discarded.
|
||||
*/
|
||||
onDataInvalidated: function DV_onDataInvalidated()
|
||||
{
|
||||
DownloadsCommon.log("Downloads data has been invalidated. Cleaning up",
|
||||
"DownloadsView.");
|
||||
|
||||
DownloadsPanel.terminate();
|
||||
|
||||
// Clear the list by replacing with a shallow copy.
|
||||
let emptyView = this.richListBox.cloneNode(false);
|
||||
this.richListBox.parentNode.replaceChild(emptyView, this.richListBox);
|
||||
this.richListBox = emptyView;
|
||||
this._viewItems = {};
|
||||
this._dataItems = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new download data item is available, either during the
|
||||
* asynchronous data load or when a new download is started.
|
||||
|
@ -1486,7 +1461,8 @@ DownloadsViewItemController.prototype = {
|
|||
|
||||
downloadsCmd_open: function DVIC_downloadsCmd_open()
|
||||
{
|
||||
this.dataItem.openLocalFile(window);
|
||||
this.dataItem.openLocalFile();
|
||||
|
||||
// We explicitly close the panel here to give the user the feedback that
|
||||
// their click has been received, and we're handling the action.
|
||||
// Otherwise, we'd have to wait for the file-type handler to execute
|
||||
|
|
|
@ -56,16 +56,11 @@ const DownloadsButton = {
|
|||
* This function is called asynchronously just after window initialization.
|
||||
*
|
||||
* NOTE: This function should limit the input/output it performs to improve
|
||||
* startup time, and in particular should not cause the Download Manager
|
||||
* service to start.
|
||||
* startup time.
|
||||
*/
|
||||
initializeIndicator: function DB_initializeIndicator()
|
||||
{
|
||||
if (!DownloadsCommon.useToolkitUI) {
|
||||
DownloadsIndicatorView.ensureInitialized();
|
||||
} else {
|
||||
DownloadsIndicatorView.ensureTerminated();
|
||||
}
|
||||
DownloadsIndicatorView.ensureInitialized();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -95,11 +90,7 @@ const DownloadsButton = {
|
|||
customizeDone: function DB_customizeDone()
|
||||
{
|
||||
this._customizing = false;
|
||||
if (!DownloadsCommon.useToolkitUI) {
|
||||
DownloadsIndicatorView.afterCustomize();
|
||||
} else {
|
||||
DownloadsIndicatorView.ensureTerminated();
|
||||
}
|
||||
DownloadsIndicatorView.afterCustomize();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -490,14 +481,7 @@ const DownloadsIndicatorView = {
|
|||
|
||||
onCommand: function DIV_onCommand(aEvent)
|
||||
{
|
||||
if (DownloadsCommon.useToolkitUI) {
|
||||
// The panel won't suppress attention for us, we need to clear now.
|
||||
DownloadsCommon.getIndicatorData(window).attention = false;
|
||||
BrowserDownloadsUI();
|
||||
} else {
|
||||
DownloadsPanel.showPanel();
|
||||
}
|
||||
|
||||
DownloadsPanel.showPanel();
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
|||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
|
||||
"resource:///modules/RecentWindow.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsLogger",
|
||||
|
@ -75,9 +73,6 @@ const nsIDM = Ci.nsIDownloadManager;
|
|||
const kDownloadsStringBundleUrl =
|
||||
"chrome://browser/locale/downloads/downloads.properties";
|
||||
|
||||
const kPrefBdmScanWhenDone = "browser.download.manager.scanWhenDone";
|
||||
const kPrefBdmAlertOnExeOpen = "browser.download.manager.alertOnEXEOpen";
|
||||
|
||||
const kDownloadsStringsRequiringFormatting = {
|
||||
sizeWithUnits: true,
|
||||
shortTimeLeftSeconds: true,
|
||||
|
@ -234,16 +229,6 @@ this.DownloadsCommon = {
|
|||
return DownloadsCommon.strings["shortTimeLeftDays"](Math.min(days, 99));
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates that we should show the simplified panel interface instead of the
|
||||
* full Download Manager window interface. The code associated with the
|
||||
* Download Manager window interface will be removed in bug 899110.
|
||||
*/
|
||||
get useToolkitUI()
|
||||
{
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether we should show visual notification on the indicator
|
||||
* when a download event is triggered.
|
||||
|
@ -269,39 +254,12 @@ this.DownloadsCommon = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Initializes the data link for both the private and non-private downloads
|
||||
* data objects.
|
||||
*
|
||||
* @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.
|
||||
* Initializes the Downloads back-end and starts receiving events for both the
|
||||
* private and non-private downloads data objects.
|
||||
*/
|
||||
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);
|
||||
initializeAllDataLinks: function () {
|
||||
DownloadsData.initializeDataLink();
|
||||
PrivateDownloadsData.initializeDataLink();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -566,15 +524,6 @@ XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
|
|||
return parseFloat(sysInfo.getProperty("version")) >= 6;
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns true to indicate that we should hook the panel to the JavaScript API
|
||||
* for downloads instead of the nsIDownloadManager back-end. The code
|
||||
* associated with nsIDownloadManager will be removed in bug 899110.
|
||||
*/
|
||||
XPCOMUtils.defineLazyGetter(DownloadsCommon, "useJSTransfer", function () {
|
||||
return true;
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// DownloadsData
|
||||
|
||||
|
@ -611,76 +560,36 @@ function DownloadsDataCtor(aPrivate) {
|
|||
// data changes.
|
||||
this._views = [];
|
||||
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
// Maps Download objects to DownloadDataItem objects.
|
||||
this._downloadToDataItemMap = new Map();
|
||||
}
|
||||
// Maps Download objects to DownloadDataItem objects.
|
||||
this._downloadToDataItemMap = new Map();
|
||||
}
|
||||
|
||||
DownloadsDataCtor.prototype = {
|
||||
/**
|
||||
* Starts receiving events for current downloads.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
initializeDataLink: function DD_initializeDataLink(aDownloadManagerService)
|
||||
initializeDataLink: function ()
|
||||
{
|
||||
// Start receiving real-time events.
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
if (!this._dataLinkInitialized) {
|
||||
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
|
||||
: Downloads.PUBLIC);
|
||||
promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
|
||||
this._dataLinkInitialized = true;
|
||||
}
|
||||
} else {
|
||||
aDownloadManagerService.addPrivacyAwareListener(this);
|
||||
Services.obs.addObserver(this, "download-manager-remove-download-guid",
|
||||
false);
|
||||
if (!this._dataLinkInitialized) {
|
||||
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
|
||||
: Downloads.PUBLIC);
|
||||
promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
|
||||
this._dataLinkInitialized = true;
|
||||
}
|
||||
},
|
||||
_dataLinkInitialized: false,
|
||||
|
||||
/**
|
||||
* Stops receiving events for current downloads and cancels any pending read.
|
||||
*/
|
||||
terminateDataLink: function DD_terminateDataLink()
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
Cu.reportError("terminateDataLink not applicable with useJSTransfer");
|
||||
return;
|
||||
}
|
||||
|
||||
this._terminateDataAccess();
|
||||
|
||||
// Stop receiving real-time events.
|
||||
Services.obs.removeObserver(this, "download-manager-remove-download-guid");
|
||||
Services.downloads.removeListener(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* True if there are finished downloads that can be removed from the list.
|
||||
*/
|
||||
get canRemoveFinished()
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
for (let [, dataItem] of Iterator(this.dataItems)) {
|
||||
if (dataItem && !dataItem.inProgress) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (this._isPrivate) {
|
||||
return Services.downloads.canCleanUpPrivate;
|
||||
} else {
|
||||
return Services.downloads.canCleanUp;
|
||||
for (let [, dataItem] of Iterator(this.dataItems)) {
|
||||
if (dataItem && !dataItem.inProgress) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -688,18 +597,10 @@ DownloadsDataCtor.prototype = {
|
|||
*/
|
||||
removeFinished: function DD_removeFinished()
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
|
||||
: Downloads.PUBLIC);
|
||||
promiseList.then(list => list.removeFinished())
|
||||
.then(null, Cu.reportError);
|
||||
} else {
|
||||
if (this._isPrivate) {
|
||||
Services.downloads.cleanUpPrivate();
|
||||
} else {
|
||||
Services.downloads.cleanUp();
|
||||
}
|
||||
}
|
||||
let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
|
||||
: Downloads.PUBLIC);
|
||||
promiseList.then(list => list.removeFinished())
|
||||
.then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -753,7 +654,7 @@ DownloadsDataCtor.prototype = {
|
|||
let wasInProgress = aDataItem.inProgress;
|
||||
let wasDone = aDataItem.done;
|
||||
|
||||
aDataItem.updateFromJSDownload();
|
||||
aDataItem.updateFromDownload();
|
||||
|
||||
if (wasInProgress && !aDataItem.inProgress) {
|
||||
aDataItem.endTime = Date.now();
|
||||
|
@ -835,394 +736,10 @@ DownloadsDataCtor.prototype = {
|
|||
function (dataItem) aView.onDataItemAdded(dataItem, false)
|
||||
);
|
||||
|
||||
// Notify the view that all data is available unless loading is in progress.
|
||||
if (!this._pendingStatement) {
|
||||
aView.onDataLoadCompleted();
|
||||
}
|
||||
// Notify the view that all data is available.
|
||||
aView.onDataLoadCompleted();
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// In-memory downloads data store
|
||||
|
||||
/**
|
||||
* Clears the loaded data.
|
||||
*/
|
||||
clear: function DD_clear()
|
||||
{
|
||||
this._terminateDataAccess();
|
||||
this.dataItems = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the data item associated with the provided source object. The
|
||||
* source can be a download object that we received from the Download Manager
|
||||
* because of a real-time notification, or a row from the downloads database,
|
||||
* during the asynchronous data load.
|
||||
*
|
||||
* In case we receive download status notifications while we are still
|
||||
* populating the list of downloads from the database, we want the real-time
|
||||
* status to take precedence over the state that is read from the database,
|
||||
* which might be older. This is achieved by creating the download item if
|
||||
* it's not already in the list, but never updating the returned object using
|
||||
* the data from the database, if the object already exists.
|
||||
*
|
||||
* @param aSource
|
||||
* Object containing the data with which the item should be initialized
|
||||
* if it doesn't already exist in the list. This should implement
|
||||
* either nsIDownload or mozIStorageRow. If the item exists, this
|
||||
* argument is only used to retrieve the download identifier.
|
||||
* @param aMayReuseGUID
|
||||
* If false, indicates that the download should not be added if a
|
||||
* download with the same identifier was removed in the meantime. This
|
||||
* ensures that, while loading the list asynchronously, downloads that
|
||||
* have been removed in the meantime do no reappear inadvertently.
|
||||
*
|
||||
* @return New or existing data item, or null if the item was deleted from the
|
||||
* list of available downloads.
|
||||
*/
|
||||
_getOrAddDataItem: function DD_getOrAddDataItem(aSource, aMayReuseGUID)
|
||||
{
|
||||
let downloadGuid = (aSource instanceof Ci.nsIDownload)
|
||||
? aSource.guid
|
||||
: aSource.getResultByName("guid");
|
||||
if (downloadGuid in this.dataItems) {
|
||||
let existingItem = this.dataItems[downloadGuid];
|
||||
if (existingItem || !aMayReuseGUID) {
|
||||
// Returns null if the download was removed and we can't reuse the item.
|
||||
return existingItem;
|
||||
}
|
||||
}
|
||||
DownloadsCommon.log("Creating a new DownloadsDataItem with downloadGuid =",
|
||||
downloadGuid);
|
||||
let dataItem = new DownloadsDataItem(aSource);
|
||||
this.dataItems[downloadGuid] = dataItem;
|
||||
|
||||
// Create the view items before returning.
|
||||
let addToStartOfList = aSource instanceof Ci.nsIDownload;
|
||||
this._views.forEach(
|
||||
function (view) view.onDataItemAdded(dataItem, addToStartOfList)
|
||||
);
|
||||
return dataItem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the data item with the specified identifier.
|
||||
*
|
||||
* This method can be called at most once per download identifier.
|
||||
*/
|
||||
_removeDataItem: function DD_removeDataItem(aDownloadId)
|
||||
{
|
||||
if (aDownloadId in this.dataItems) {
|
||||
let dataItem = this.dataItems[aDownloadId];
|
||||
this.dataItems[aDownloadId] = null;
|
||||
this._views.forEach(
|
||||
function (view) view.onDataItemRemoved(dataItem)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Persistent data loading
|
||||
|
||||
/**
|
||||
* Represents an executing statement, allowing its cancellation.
|
||||
*/
|
||||
_pendingStatement: null,
|
||||
|
||||
/**
|
||||
* Indicates which kind of items from the persistent downloads database have
|
||||
* been fully loaded in memory and are available to the views. This can
|
||||
* assume the value of one of the kLoad constants.
|
||||
*/
|
||||
_loadState: 0,
|
||||
|
||||
/** No downloads have been fully loaded yet. */
|
||||
get kLoadNone() 0,
|
||||
/** All the active downloads in the database are loaded in memory. */
|
||||
get kLoadActive() 1,
|
||||
/** All the downloads in the database are loaded in memory. */
|
||||
get kLoadAll() 2,
|
||||
|
||||
/**
|
||||
* Reloads the specified kind of downloads from the persistent database. This
|
||||
* method must only be called when Private Browsing Mode is disabled.
|
||||
*
|
||||
* @param aActiveOnly
|
||||
* True to load only active downloads from the database.
|
||||
*/
|
||||
ensurePersistentDataLoaded:
|
||||
function DD_ensurePersistentDataLoaded(aActiveOnly)
|
||||
{
|
||||
if (this == PrivateDownloadsData) {
|
||||
Cu.reportError("ensurePersistentDataLoaded should not be called on PrivateDownloadsData");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._pendingStatement) {
|
||||
// We are already in the process of reloading all downloads.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aActiveOnly) {
|
||||
if (this._loadState == this.kLoadNone) {
|
||||
DownloadsCommon.log("Loading only active downloads from the persistence database");
|
||||
// Indicate to the views that a batch loading operation is in progress.
|
||||
this._views.forEach(
|
||||
function (view) view.onDataLoadStarting()
|
||||
);
|
||||
|
||||
// Reload the list using the Download Manager service. The list is
|
||||
// returned in no particular order.
|
||||
let downloads = Services.downloads.activeDownloads;
|
||||
while (downloads.hasMoreElements()) {
|
||||
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
|
||||
this._getOrAddDataItem(download, true);
|
||||
}
|
||||
this._loadState = this.kLoadActive;
|
||||
|
||||
// Indicate to the views that the batch loading operation is complete.
|
||||
this._views.forEach(
|
||||
function (view) view.onDataLoadCompleted()
|
||||
);
|
||||
DownloadsCommon.log("Active downloads done loading.");
|
||||
}
|
||||
} else {
|
||||
if (this._loadState != this.kLoadAll) {
|
||||
// Load only the relevant columns from the downloads database. The
|
||||
// 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.
|
||||
DownloadsCommon.log("Loading all downloads from the persistence database.");
|
||||
let dbConnection = Services.downloads.DBConnection;
|
||||
let statement = dbConnection.createAsyncStatement(
|
||||
"SELECT guid, target, name, source, referrer, state, "
|
||||
+ "startTime, endTime, currBytes, maxBytes "
|
||||
+ "FROM moz_downloads "
|
||||
+ "ORDER BY startTime DESC"
|
||||
);
|
||||
try {
|
||||
this._pendingStatement = statement.executeAsync(this);
|
||||
} finally {
|
||||
statement.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels any pending data access and ensures views are notified.
|
||||
*/
|
||||
_terminateDataAccess: function DD_terminateDataAccess()
|
||||
{
|
||||
if (this._pendingStatement) {
|
||||
this._pendingStatement.cancel();
|
||||
this._pendingStatement = null;
|
||||
}
|
||||
|
||||
// Close all the views on the current data. Create a copy of the array
|
||||
// because some views might unregister while processing this event.
|
||||
Array.slice(this._views, 0).forEach(
|
||||
function (view) view.onDataInvalidated()
|
||||
);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageStatementCallback
|
||||
|
||||
handleResult: function DD_handleResult(aResultSet)
|
||||
{
|
||||
for (let row = aResultSet.getNextRow();
|
||||
row;
|
||||
row = aResultSet.getNextRow()) {
|
||||
// Add the download to the list and initialize it with the data we read,
|
||||
// unless we already received a notification providing more reliable
|
||||
// information for this download.
|
||||
this._getOrAddDataItem(row, false);
|
||||
}
|
||||
},
|
||||
|
||||
handleError: function DD_handleError(aError)
|
||||
{
|
||||
DownloadsCommon.error("Database statement execution error (",
|
||||
aError.result, "): ", aError.message);
|
||||
},
|
||||
|
||||
handleCompletion: function DD_handleCompletion(aReason)
|
||||
{
|
||||
DownloadsCommon.log("Loading all downloads from database completed with reason:",
|
||||
aReason);
|
||||
this._pendingStatement = null;
|
||||
|
||||
// To ensure that we don't inadvertently delete more downloads from the
|
||||
// database than needed on shutdown, we should update the load state only if
|
||||
// the operation completed successfully.
|
||||
if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
|
||||
this._loadState = this.kLoadAll;
|
||||
}
|
||||
|
||||
// Indicate to the views that the batch loading operation is complete, even
|
||||
// if the lookup failed or was canceled. The only possible glitch happens
|
||||
// in case the database backend changes while loading data, when the views
|
||||
// would open and immediately close. This case is rare enough not to need a
|
||||
// special treatment.
|
||||
this._views.forEach(
|
||||
function (view) view.onDataLoadCompleted()
|
||||
);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIObserver
|
||||
|
||||
observe: function DD_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
switch (aTopic) {
|
||||
case "download-manager-remove-download-guid":
|
||||
// If a single download was removed, remove the corresponding data item.
|
||||
if (aSubject) {
|
||||
let downloadGuid = aSubject.QueryInterface(Ci.nsISupportsCString).data;
|
||||
DownloadsCommon.log("A single download with id",
|
||||
downloadGuid, "was removed.");
|
||||
this._removeDataItem(downloadGuid);
|
||||
break;
|
||||
}
|
||||
|
||||
// Multiple downloads have been removed. Iterate over known downloads
|
||||
// and remove those that don't exist anymore.
|
||||
DownloadsCommon.log("Multiple downloads were removed.");
|
||||
for each (let dataItem in this.dataItems) {
|
||||
if (dataItem) {
|
||||
// Bug 449811 - We have to bind to the dataItem because Javascript
|
||||
// doesn't do fresh let-bindings per loop iteration.
|
||||
let dataItemBinding = dataItem;
|
||||
Services.downloads.getDownloadByGUID(dataItemBinding.downloadGuid,
|
||||
function(aStatus, aResult) {
|
||||
if (aStatus == Components.results.NS_ERROR_NOT_AVAILABLE) {
|
||||
DownloadsCommon.log("Removing download with id",
|
||||
dataItemBinding.downloadGuid);
|
||||
this._removeDataItem(dataItemBinding.downloadGuid);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIDownloadProgressListener
|
||||
|
||||
onDownloadStateChange: function DD_onDownloadStateChange(aOldState, 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.
|
||||
let isNew = aOldState == nsIDM.DOWNLOAD_NOTSTARTED ||
|
||||
aOldState == nsIDM.DOWNLOAD_QUEUED;
|
||||
|
||||
let dataItem = this._getOrAddDataItem(aDownload, isNew);
|
||||
if (!dataItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
let wasInProgress = dataItem.inProgress;
|
||||
|
||||
DownloadsCommon.log("A download changed its state to:", aDownload.state);
|
||||
dataItem.state = aDownload.state;
|
||||
dataItem.referrer = aDownload.referrer && aDownload.referrer.spec;
|
||||
dataItem.resumable = aDownload.resumable;
|
||||
dataItem.startTime = Math.round(aDownload.startTime / 1000);
|
||||
dataItem.currBytes = aDownload.amountTransferred;
|
||||
dataItem.maxBytes = aDownload.size;
|
||||
|
||||
if (wasInProgress && !dataItem.inProgress) {
|
||||
dataItem.endTime = Date.now();
|
||||
}
|
||||
|
||||
// When a download is retried, we create a different download object from
|
||||
// the database with the same ID as before. This means that the nsIDownload
|
||||
// that the dataItem holds might now need updating.
|
||||
//
|
||||
// We only overwrite this in the event that _download exists, because if it
|
||||
// doesn't, that means that no caller ever tried to get the nsIDownload,
|
||||
// which means it was never retrieved and doesn't need to be overwritten.
|
||||
if (dataItem._download) {
|
||||
dataItem._download = aDownload;
|
||||
}
|
||||
|
||||
for (let view of this._views) {
|
||||
try {
|
||||
view.getViewItem(dataItem).onStateChange(aOldState);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNew && !dataItem.newDownloadNotified) {
|
||||
dataItem.newDownloadNotified = true;
|
||||
this._notifyDownloadEvent("start");
|
||||
}
|
||||
|
||||
// This is a final state of which we are only notified once.
|
||||
if (dataItem.done) {
|
||||
this._notifyDownloadEvent("finish");
|
||||
}
|
||||
|
||||
// TODO Bug 830415: this isn't the right place to set these annotation.
|
||||
// It should be set it in places' nsIDownloadHistory implementation.
|
||||
if (!this._isPrivate && !dataItem.inProgress) {
|
||||
let downloadMetaData = { state: dataItem.state,
|
||||
endTime: dataItem.endTime };
|
||||
if (dataItem.done)
|
||||
downloadMetaData.fileSize = dataItem.maxBytes;
|
||||
|
||||
try {
|
||||
PlacesUtils.annotations.setPageAnnotation(
|
||||
NetUtil.newURI(dataItem.uri), "downloads/metaData", JSON.stringify(downloadMetaData), 0,
|
||||
PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
|
||||
}
|
||||
catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onProgressChange: function DD_onProgressChange(aWebProgress, aRequest,
|
||||
aCurSelfProgress,
|
||||
aMaxSelfProgress,
|
||||
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;
|
||||
}
|
||||
|
||||
dataItem.currBytes = aDownload.amountTransferred;
|
||||
dataItem.maxBytes = aDownload.size;
|
||||
dataItem.speed = aDownload.speed;
|
||||
dataItem.percentComplete = aDownload.percentComplete;
|
||||
|
||||
this._views.forEach(
|
||||
function (view) view.getViewItem(dataItem).onProgressChange()
|
||||
);
|
||||
},
|
||||
|
||||
onStateChange: function () { },
|
||||
|
||||
onSecurityChange: function () { },
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Notifications sent to the most recent browser window only
|
||||
|
||||
|
@ -1252,10 +769,6 @@ DownloadsDataCtor.prototype = {
|
|||
_notifyDownloadEvent: function DD_notifyDownloadEvent(aType)
|
||||
{
|
||||
DownloadsCommon.log("Attempting to notify that a new download has started or finished.");
|
||||
if (DownloadsCommon.useToolkitUI) {
|
||||
DownloadsCommon.log("Cancelling notification - we're using the toolkit downloads manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the panel in the most recent browser window, if present.
|
||||
let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate });
|
||||
|
@ -1288,25 +801,24 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
|
|||
//// DownloadsDataItem
|
||||
|
||||
/**
|
||||
* Represents a single item in the list of downloads. This object either wraps
|
||||
* an existing nsIDownload from the Download Manager, or provides the same
|
||||
* information read directly from the downloads database, with the possibility
|
||||
* of querying the nsIDownload lazily, for performance reasons.
|
||||
* Represents a single item in the list of downloads.
|
||||
*
|
||||
* @param aSource
|
||||
* Object containing the data with which the item should be initialized.
|
||||
* This should implement either nsIDownload or mozIStorageRow. If the
|
||||
* JavaScript API for downloads is enabled, this is a Download object.
|
||||
* The endTime property is initialized to the current date and time.
|
||||
*
|
||||
* @param aDownload
|
||||
* The Download object with the current state.
|
||||
*/
|
||||
function DownloadsDataItem(aSource)
|
||||
function DownloadsDataItem(aDownload)
|
||||
{
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
this._initFromJSDownload(aSource);
|
||||
} else if (aSource instanceof Ci.nsIDownload) {
|
||||
this._initFromDownload(aSource);
|
||||
} else {
|
||||
this._initFromDataRow(aSource);
|
||||
}
|
||||
this._download = aDownload;
|
||||
|
||||
this.downloadGuid = "id:" + this._autoIncrementId;
|
||||
this.file = aDownload.target.path;
|
||||
this.target = OS.Path.basename(aDownload.target.path);
|
||||
this.uri = aDownload.source.url;
|
||||
this.endTime = Date.now();
|
||||
|
||||
this.updateFromDownload();
|
||||
}
|
||||
|
||||
DownloadsDataItem.prototype = {
|
||||
|
@ -1318,30 +830,9 @@ DownloadsDataItem.prototype = {
|
|||
__lastId: 0,
|
||||
|
||||
/**
|
||||
* Initializes this object from the JavaScript API for downloads.
|
||||
*
|
||||
* The endTime property is initialized to the current date and time.
|
||||
*
|
||||
* @param aDownload
|
||||
* The Download object with the current state.
|
||||
* Updates this object from the underlying Download object.
|
||||
*/
|
||||
_initFromJSDownload: function (aDownload)
|
||||
{
|
||||
this._download = aDownload;
|
||||
|
||||
this.downloadGuid = "id:" + this._autoIncrementId;
|
||||
this.file = aDownload.target.path;
|
||||
this.target = OS.Path.basename(aDownload.target.path);
|
||||
this.uri = aDownload.source.url;
|
||||
this.endTime = Date.now();
|
||||
|
||||
this.updateFromJSDownload();
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates this object from the JavaScript API for downloads.
|
||||
*/
|
||||
updateFromJSDownload: function ()
|
||||
updateFromDownload: function ()
|
||||
{
|
||||
// Collapse state using the correct priority.
|
||||
if (this._download.succeeded) {
|
||||
|
@ -1370,115 +861,6 @@ DownloadsDataItem.prototype = {
|
|||
this.percentComplete = this._download.progress;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes this object from a download object of the Download Manager.
|
||||
*
|
||||
* The endTime property is initialized to the current date and time.
|
||||
*
|
||||
* @param aDownload
|
||||
* The nsIDownload with the current state.
|
||||
*/
|
||||
_initFromDownload: function DDI_initFromDownload(aDownload)
|
||||
{
|
||||
this._download = aDownload;
|
||||
|
||||
// Fetch all the download properties eagerly.
|
||||
this.downloadGuid = aDownload.guid;
|
||||
this.file = aDownload.target.spec;
|
||||
this.target = aDownload.displayName;
|
||||
this.uri = aDownload.source.spec;
|
||||
this.referrer = aDownload.referrer && aDownload.referrer.spec;
|
||||
this.state = aDownload.state;
|
||||
this.startTime = Math.round(aDownload.startTime / 1000);
|
||||
this.endTime = Date.now();
|
||||
this.currBytes = aDownload.amountTransferred;
|
||||
this.maxBytes = aDownload.size;
|
||||
this.resumable = aDownload.resumable;
|
||||
this.speed = aDownload.speed;
|
||||
this.percentComplete = aDownload.percentComplete;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes this object from a data row in the downloads database, without
|
||||
* querying the associated nsIDownload object, to improve performance when
|
||||
* loading the list of downloads asynchronously.
|
||||
*
|
||||
* When this object is initialized in this way, accessing the "download"
|
||||
* property loads the underlying nsIDownload object synchronously, and should
|
||||
* be avoided unless the object is really required.
|
||||
*
|
||||
* @param aStorageRow
|
||||
* The mozIStorageRow from the downloads database.
|
||||
*/
|
||||
_initFromDataRow: function DDI_initFromDataRow(aStorageRow)
|
||||
{
|
||||
// Get the download properties from the data row.
|
||||
this._download = null;
|
||||
this.downloadGuid = aStorageRow.getResultByName("guid");
|
||||
this.file = aStorageRow.getResultByName("target");
|
||||
this.target = aStorageRow.getResultByName("name");
|
||||
this.uri = aStorageRow.getResultByName("source");
|
||||
this.referrer = aStorageRow.getResultByName("referrer");
|
||||
this.state = aStorageRow.getResultByName("state");
|
||||
this.startTime = Math.round(aStorageRow.getResultByName("startTime") / 1000);
|
||||
this.endTime = Math.round(aStorageRow.getResultByName("endTime") / 1000);
|
||||
this.currBytes = aStorageRow.getResultByName("currBytes");
|
||||
this.maxBytes = aStorageRow.getResultByName("maxBytes");
|
||||
|
||||
// Now we have to determine if the download is resumable, but don't want to
|
||||
// access the underlying download object unnecessarily. The only case where
|
||||
// the property is relevant is when we are currently downloading data, and
|
||||
// in this case the download object is already loaded in memory or will be
|
||||
// loaded very soon in any case. In all the other cases, including a paused
|
||||
// download, we assume that the download is resumable. The property will be
|
||||
// updated as soon as the underlying download state changes.
|
||||
|
||||
// We'll start by assuming we're resumable, and then if we're downloading,
|
||||
// update resumable property in case we were wrong.
|
||||
this.resumable = true;
|
||||
|
||||
if (this.state == nsIDM.DOWNLOAD_DOWNLOADING) {
|
||||
this.getDownload(function(aDownload) {
|
||||
this.resumable = aDownload.resumable;
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// Compute the other properties without accessing the download object.
|
||||
this.speed = 0;
|
||||
this.percentComplete = this.maxBytes <= 0
|
||||
? -1
|
||||
: Math.round(this.currBytes / this.maxBytes * 100);
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous getter for the download object corresponding to this data item.
|
||||
*
|
||||
* @param aCallback
|
||||
* A callback function which will be called when the download object is
|
||||
* available. It should accept one argument which will be the download
|
||||
* object.
|
||||
*/
|
||||
getDownload: function DDI_getDownload(aCallback) {
|
||||
if (this._download) {
|
||||
// Return the download object asynchronously to the caller
|
||||
let download = this._download;
|
||||
Services.tm.mainThread.dispatch(function () aCallback(download),
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
} else {
|
||||
Services.downloads.getDownloadByGUID(this.downloadGuid,
|
||||
function(aStatus, aResult) {
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
Cu.reportError(
|
||||
new Components.Exception("Cannot retrieve download for GUID: " +
|
||||
this.downloadGuid));
|
||||
} else {
|
||||
this._download = aResult;
|
||||
aCallback(aResult);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether the download is proceeding normally, and not finished
|
||||
* yet. This includes paused downloads. When this property is true, the
|
||||
|
@ -1600,22 +982,9 @@ DownloadsDataItem.prototype = {
|
|||
|
||||
/**
|
||||
* Open the target file for this download.
|
||||
*
|
||||
* @param aOwnerWindow
|
||||
* The window with which the required action is associated.
|
||||
* @throws if the file cannot be opened.
|
||||
*/
|
||||
openLocalFile: function DDI_openLocalFile(aOwnerWindow) {
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
this._download.launch().then(null, Cu.reportError);
|
||||
return;
|
||||
}
|
||||
|
||||
this.getDownload(function(aDownload) {
|
||||
DownloadsCommon.openDownloadedFile(this.localFile,
|
||||
aDownload.MIMEInfo,
|
||||
aOwnerWindow);
|
||||
}.bind(this));
|
||||
openLocalFile: function () {
|
||||
this._download.launch().then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1630,26 +999,11 @@ DownloadsDataItem.prototype = {
|
|||
* @throws if the download is not resumable or if has already done.
|
||||
*/
|
||||
togglePauseResume: function DDI_togglePauseResume() {
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
if (this._download.stopped) {
|
||||
this._download.start();
|
||||
} else {
|
||||
this._download.cancel();
|
||||
}
|
||||
return;
|
||||
if (this._download.stopped) {
|
||||
this._download.start();
|
||||
} else {
|
||||
this._download.cancel();
|
||||
}
|
||||
|
||||
if (!this.inProgress || !this.resumable)
|
||||
throw new Error("The given download cannot be paused or resumed");
|
||||
|
||||
this.getDownload(function(aDownload) {
|
||||
if (this.inProgress) {
|
||||
if (this.paused)
|
||||
aDownload.resume();
|
||||
else
|
||||
aDownload.pause();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1657,73 +1011,25 @@ DownloadsDataItem.prototype = {
|
|||
* @throws if we cannot.
|
||||
*/
|
||||
retry: function DDI_retry() {
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
this._download.start();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.canRetry)
|
||||
throw new Error("Cannot retry this download");
|
||||
|
||||
this.getDownload(function(aDownload) {
|
||||
aDownload.retry();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Support function that deletes the local file for a download. This is
|
||||
* used in cases where the Download Manager service doesn't delete the file
|
||||
* from disk when cancelling. See bug 732924.
|
||||
*/
|
||||
_ensureLocalFileRemoved: function DDI__ensureLocalFileRemoved()
|
||||
{
|
||||
try {
|
||||
let localFile = this.localFile;
|
||||
if (localFile.exists()) {
|
||||
localFile.remove(false);
|
||||
}
|
||||
} catch (ex) { }
|
||||
this._download.start();
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancels the download.
|
||||
* @throws if the download is already done.
|
||||
*/
|
||||
cancel: function() {
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
this._download.cancel();
|
||||
this._download.removePartialData().then(null, Cu.reportError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.inProgress)
|
||||
throw new Error("Cannot cancel this download");
|
||||
|
||||
this.getDownload(function (aDownload) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}.bind(this));
|
||||
this._download.cancel();
|
||||
this._download.removePartialData().then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the download.
|
||||
*/
|
||||
remove: function DDI_remove() {
|
||||
if (DownloadsCommon.useJSTransfer) {
|
||||
Downloads.getList(Downloads.ALL)
|
||||
.then(list => list.remove(this._download))
|
||||
.then(() => this._download.finalize(true))
|
||||
.then(null, Cu.reportError);
|
||||
return;
|
||||
}
|
||||
|
||||
this.getDownload(function (aDownload) {
|
||||
if (this.inProgress) {
|
||||
aDownload.cancel();
|
||||
this._ensureLocalFileRemoved();
|
||||
}
|
||||
aDownload.remove();
|
||||
}.bind(this));
|
||||
Downloads.getList(Downloads.ALL)
|
||||
.then(list => list.remove(this._download))
|
||||
.then(() => this._download.finalize(true))
|
||||
.then(null, Cu.reportError);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1838,18 +1144,6 @@ const DownloadsViewPrototype = {
|
|||
this._loading = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the downloads database becomes unavailable (for example, we
|
||||
* entered Private Browsing Mode and the database backend changed).
|
||||
* References to existing data should be discarded.
|
||||
*
|
||||
* @note Subclasses should override this.
|
||||
*/
|
||||
onDataInvalidated: function DVP_onDataInvalidated()
|
||||
{
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new download data item is available, either during the
|
||||
* asynchronous data load or when a new download is started.
|
||||
|
@ -1968,16 +1262,6 @@ DownloadsIndicatorDataCtor.prototype = {
|
|||
this._updateViews();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the downloads database becomes unavailable (for example, we
|
||||
* entered Private Browsing Mode and the database backend changed).
|
||||
* References to existing data should be discarded.
|
||||
*/
|
||||
onDataInvalidated: function DID_onDataInvalidated()
|
||||
{
|
||||
this._itemCount = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a new download data item is available, either during the
|
||||
* asynchronous data load or when a new download is started.
|
||||
|
@ -2271,11 +1555,6 @@ DownloadsSummaryData.prototype = {
|
|||
this._updateViews();
|
||||
},
|
||||
|
||||
onDataInvalidated: function DSD_onDataInvalidated()
|
||||
{
|
||||
this._dataItems = [];
|
||||
},
|
||||
|
||||
onDataItemAdded: function DSD_onDataItemAdded(aDataItem, aNewest)
|
||||
{
|
||||
if (aNewest) {
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
|
||||
/* 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/. */
|
||||
* 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/. */
|
||||
|
||||
/**
|
||||
* This component listens to notifications for startup, shutdown and session
|
||||
* restore, controlling which downloads should be loaded from the database.
|
||||
*
|
||||
* To avoid affecting startup performance, this component monitors the current
|
||||
* session restore state, but defers the actual downloads data manipulation
|
||||
* until the Download Manager service is loaded.
|
||||
* This component enables the JavaScript API for downloads at startup. This
|
||||
* will eventually be removed when nsIDownloadManager will not be available
|
||||
* anymore (bug 851471).
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
@ -23,44 +20,18 @@ const Ci = Components.interfaces;
|
|||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||
"resource:///modules/DownloadsCommon.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
|
||||
"@mozilla.org/browser/sessionstartup;1",
|
||||
"nsISessionStartup");
|
||||
|
||||
const kObservedTopics = [
|
||||
"sessionstore-windows-restored",
|
||||
"sessionstore-browser-state-restored",
|
||||
"download-manager-initialized",
|
||||
"download-manager-change-retention",
|
||||
"last-pb-context-exited",
|
||||
"browser-lastwindow-close-granted",
|
||||
"quit-application",
|
||||
"profile-change-teardown",
|
||||
];
|
||||
|
||||
/**
|
||||
* CID of our implementation of nsIDownloadManagerUI.
|
||||
* CID and Contract ID of our implementation of nsIDownloadManagerUI.
|
||||
*/
|
||||
const kDownloadsUICid = Components.ID("{4d99321e-d156-455b-81f7-e7aa2308134f}");
|
||||
|
||||
/**
|
||||
* Contract ID of the service implementing nsIDownloadManagerUI.
|
||||
*/
|
||||
const kDownloadsUIContractId = "@mozilla.org/download-manager-ui;1";
|
||||
|
||||
/**
|
||||
* CID of the JavaScript implementation of nsITransfer.
|
||||
* CID and Contract ID of the JavaScript implementation of nsITransfer.
|
||||
*/
|
||||
const kTransferCid = Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}");
|
||||
|
||||
/**
|
||||
* Contract ID of the service implementing nsITransfer.
|
||||
*/
|
||||
const kTransferContractId = "@mozilla.org/transfer;1";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -76,204 +47,31 @@ DownloadsStartup.prototype = {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsISupports
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIObserver
|
||||
|
||||
observe: function DS_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
switch (aTopic) {
|
||||
case "profile-after-change":
|
||||
// Override Toolkit's nsIDownloadManagerUI implementation with our own.
|
||||
// This must be done at application startup and not in the manifest to
|
||||
// ensure that our implementation overrides the original one.
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
|
||||
.registerFactory(kDownloadsUICid, "",
|
||||
kDownloadsUIContractId, null);
|
||||
|
||||
// Override Toolkit's nsITransfer implementation with the one from the
|
||||
// JavaScript API for downloads. This will eventually be removed when
|
||||
// nsIDownloadManager will not be available anymore (bug 851471). The
|
||||
// old code in this module will be removed in bug 899110.
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
|
||||
.registerFactory(kTransferCid, "",
|
||||
kTransferContractId, null);
|
||||
break;
|
||||
|
||||
case "sessionstore-windows-restored":
|
||||
case "sessionstore-browser-state-restored":
|
||||
// Unless there is no saved session, there is a chance that we are
|
||||
// starting up after a restart or a crash. We should check the disk
|
||||
// database to see if there are completed downloads to recover and show
|
||||
// in the panel, in addition to in-progress downloads.
|
||||
if (gSessionStartup.sessionType != Ci.nsISessionStartup.NO_SESSION) {
|
||||
this._restoringSession = true;
|
||||
}
|
||||
this._ensureDataLoaded();
|
||||
break;
|
||||
|
||||
case "download-manager-initialized":
|
||||
// Don't initialize the JavaScript data and user interface layer if we
|
||||
// are initializing the Download Manager service during shutdown.
|
||||
if (this._shuttingDown) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 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.initializeAllDataLinks(
|
||||
aSubject.QueryInterface(Ci.nsIDownloadManager));
|
||||
|
||||
this._downloadsServiceInitialized = true;
|
||||
|
||||
// Since this notification is generated during the getService call and
|
||||
// we need to get the Download Manager service ourselves, we must post
|
||||
// the handler on the event queue to be executed later.
|
||||
Services.tm.mainThread.dispatch(this._ensureDataLoaded.bind(this),
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
break;
|
||||
|
||||
case "download-manager-change-retention":
|
||||
// If we're using the Downloads Panel, we override the retention
|
||||
// preference to always retain downloads on completion.
|
||||
if (!DownloadsCommon.useToolkitUI) {
|
||||
aSubject.QueryInterface(Ci.nsISupportsPRInt32).data = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case "browser-lastwindow-close-granted":
|
||||
// When using the panel interface, downloads that are already completed
|
||||
// should be removed when the last full browser window is closed. This
|
||||
// event is invoked only if the application is not shutting down yet.
|
||||
// If the Download Manager service is not initialized, we don't want to
|
||||
// initialize it just to clean up completed downloads, because they can
|
||||
// be present only in case there was a browser crash or restart.
|
||||
if (this._downloadsServiceInitialized &&
|
||||
!DownloadsCommon.useToolkitUI) {
|
||||
Services.downloads.cleanUp();
|
||||
}
|
||||
break;
|
||||
|
||||
case "last-pb-context-exited":
|
||||
// Similar to the above notification, but for private downloads.
|
||||
if (this._downloadsServiceInitialized &&
|
||||
!DownloadsCommon.useToolkitUI) {
|
||||
Services.downloads.cleanUpPrivate();
|
||||
}
|
||||
break;
|
||||
|
||||
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
|
||||
// service is not initialized, we don't want to initialize it just to
|
||||
// clean up completed downloads, because they can be present only in
|
||||
// case there was a browser crash or restart.
|
||||
this._shuttingDown = true;
|
||||
if (!this._downloadsServiceInitialized) {
|
||||
break;
|
||||
}
|
||||
|
||||
DownloadsCommon.terminateAllDataLinks();
|
||||
|
||||
// When using the panel interface, downloads that are already completed
|
||||
// should be removed when quitting the application.
|
||||
if (!DownloadsCommon.useToolkitUI && aData != "restart") {
|
||||
this._cleanupOnShutdown = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case "profile-change-teardown":
|
||||
// If we need to clean up, we must do it synchronously after all the
|
||||
// "quit-application" listeners are invoked, so that the Download
|
||||
// Manager service has a chance to pause or cancel in-progress downloads
|
||||
// before we remove completed downloads from the list. Note that, since
|
||||
// "quit-application" was invoked, we've already exited Private Browsing
|
||||
// Mode, thus we are always working on the disk database.
|
||||
if (this._cleanupOnShutdown) {
|
||||
Services.downloads.cleanUp();
|
||||
}
|
||||
|
||||
if (!DownloadsCommon.useToolkitUI) {
|
||||
// If we got this far, that means that we finished our first session
|
||||
// with the Downloads Panel without crashing. This means that we don't
|
||||
// have to force displaying only active downloads on the next startup
|
||||
// now.
|
||||
this._firstSessionCompleted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Private
|
||||
|
||||
/**
|
||||
* Indicates whether we're restoring a previous session. This is used by
|
||||
* _recoverAllDownloads to determine whether or not we should load and
|
||||
* display all downloads data, or restrict it to only the active downloads.
|
||||
*/
|
||||
_restoringSession: false,
|
||||
|
||||
/**
|
||||
* Indicates whether the Download Manager service has been initialized. This
|
||||
* flag is required because we want to avoid accessing the service immediately
|
||||
* at browser startup. The service will start when the user first requests a
|
||||
* download, or some time after browser startup.
|
||||
*/
|
||||
_downloadsServiceInitialized: false,
|
||||
|
||||
/**
|
||||
* True while we are processing the "quit-application" event, and later.
|
||||
*/
|
||||
_shuttingDown: false,
|
||||
|
||||
/**
|
||||
* True during shutdown if we need to remove completed downloads.
|
||||
*/
|
||||
_cleanupOnShutdown: false,
|
||||
|
||||
/**
|
||||
* True if we should display all downloads, as opposed to just active
|
||||
* downloads. We decide to display all downloads if we're restoring a session,
|
||||
* or if we're using the Downloads Panel anytime after the first session with
|
||||
* it has completed.
|
||||
*/
|
||||
get _recoverAllDownloads() {
|
||||
return this._restoringSession ||
|
||||
(!DownloadsCommon.useToolkitUI && this._firstSessionCompleted);
|
||||
},
|
||||
|
||||
/**
|
||||
* True if we've ever completed a session with the Downloads Panel enabled.
|
||||
*/
|
||||
get _firstSessionCompleted() {
|
||||
return Services.prefs
|
||||
.getBoolPref("browser.download.panel.firstSessionCompleted");
|
||||
},
|
||||
|
||||
set _firstSessionCompleted(aValue) {
|
||||
Services.prefs.setBoolPref("browser.download.panel.firstSessionCompleted",
|
||||
aValue);
|
||||
return aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensures that persistent download data is reloaded at the appropriate time.
|
||||
*/
|
||||
_ensureDataLoaded: function DS_ensureDataLoaded()
|
||||
{
|
||||
if (!this._downloadsServiceInitialized) {
|
||||
if (aTopic != "profile-after-change") {
|
||||
Cu.reportError("Unexpected observer notification.");
|
||||
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.ensureAllPersistentDataLoaded(!this._recoverAllDownloads);
|
||||
}
|
||||
// Override Toolkit's nsIDownloadManagerUI implementation with our own.
|
||||
// This must be done at application startup and not in the manifest to
|
||||
// ensure that our implementation overrides the original one.
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
|
||||
.registerFactory(kDownloadsUICid, "",
|
||||
kDownloadsUIContractId, null);
|
||||
|
||||
// Override Toolkit's nsITransfer implementation with the one from the
|
||||
// JavaScript API for downloads.
|
||||
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
|
||||
.registerFactory(kTransferCid, "",
|
||||
kTransferContractId, null);
|
||||
},
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
|
||||
/* 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/. */
|
||||
* 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/. */
|
||||
|
||||
/**
|
||||
* This component implements the nsIDownloadManagerUI interface and opens the
|
||||
* downloads panel in the most recent browser window when requested.
|
||||
*
|
||||
* If a specific preference is set, this component transparently forwards all
|
||||
* calls to the original implementation in Toolkit, that shows the window UI.
|
||||
* Downloads view for the most recent browser window when requested.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
@ -40,11 +37,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
|||
|
||||
function DownloadsUI()
|
||||
{
|
||||
XPCOMUtils.defineLazyGetter(this, "_toolkitUI", function () {
|
||||
// Create Toolkit's nsIDownloadManagerUI implementation.
|
||||
return Components.classesByID["{7dfdf0d1-aff6-4a34-bad1-d0fe74601642}"]
|
||||
.getService(Ci.nsIDownloadManagerUI);
|
||||
});
|
||||
}
|
||||
|
||||
DownloadsUI.prototype = {
|
||||
|
@ -62,11 +54,6 @@ DownloadsUI.prototype = {
|
|||
|
||||
show: function DUI_show(aWindowContext, aDownload, aReason, aUsePrivateUI)
|
||||
{
|
||||
if (DownloadsCommon.useToolkitUI) {
|
||||
this._toolkitUI.show(aWindowContext, aDownload, aReason, aUsePrivateUI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aReason) {
|
||||
aReason = Ci.nsIDownloadManagerUI.REASON_USER_INTERACTED;
|
||||
}
|
||||
|
@ -92,27 +79,17 @@ DownloadsUI.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
get visible()
|
||||
{
|
||||
// If we're still using the toolkit downloads manager, delegate the call
|
||||
// to it. Otherwise, return true for now, until we decide on how we want
|
||||
// to indicate that a new download has started if a browser window is
|
||||
// not available or minimized.
|
||||
return DownloadsCommon.useToolkitUI ? this._toolkitUI.visible : true;
|
||||
},
|
||||
get visible() true,
|
||||
|
||||
getAttention: function DUI_getAttention()
|
||||
{
|
||||
if (DownloadsCommon.useToolkitUI) {
|
||||
this._toolkitUI.getAttention();
|
||||
}
|
||||
},
|
||||
getAttention: function () {},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Private
|
||||
|
||||
/**
|
||||
* Helper function that opens the download manager UI.
|
||||
*/
|
||||
_showDownloadManagerUI:
|
||||
function DUI_showDownloadManagerUI(aWindowContext, aUsePrivateUI)
|
||||
_showDownloadManagerUI: function (aWindowContext, aUsePrivateUI)
|
||||
{
|
||||
// If we weren't given a window context, try to find a browser window
|
||||
// to use as our parent - and if that doesn't work, error out and give up.
|
||||
|
|
|
@ -17,8 +17,6 @@ var gMainPane = {
|
|||
|
||||
this.updateBrowserStartupLastSession();
|
||||
|
||||
this.setupDownloadsWindowOptions();
|
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
|
@ -39,17 +37,6 @@ var gMainPane = {
|
|||
|
||||
},
|
||||
|
||||
setupDownloadsWindowOptions: function ()
|
||||
{
|
||||
let showWhenDownloading = document.getElementById("showWhenDownloading");
|
||||
let closeWhenDone = document.getElementById("closeWhenDone");
|
||||
|
||||
// These radio buttons should be hidden when the Downloads Panel is enabled.
|
||||
let shouldHide = !DownloadsCommon.useToolkitUI;
|
||||
showWhenDownloading.hidden = shouldHide;
|
||||
closeWhenDone.hidden = shouldHide;
|
||||
},
|
||||
|
||||
// HOME PAGE
|
||||
|
||||
/*
|
||||
|
@ -201,12 +188,6 @@ var gMainPane = {
|
|||
/*
|
||||
* Preferences:
|
||||
*
|
||||
* browser.download.showWhenStarting - bool
|
||||
* True if the Download Manager should be opened when a download is
|
||||
* started, false if it shouldn't be opened.
|
||||
* browser.download.closeWhenDone - bool
|
||||
* True if the Download Manager should be closed when all downloads
|
||||
* complete, false if it should be left open.
|
||||
* browser.download.useDownloadDir - bool
|
||||
* True - Save files directly to the folder configured via the
|
||||
* browser.download.folderList preference.
|
||||
|
@ -234,30 +215,6 @@ var gMainPane = {
|
|||
* deprecated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Updates preferences which depend upon the value of the preference which
|
||||
* determines whether the Downloads manager is opened at the start of a
|
||||
* download.
|
||||
*/
|
||||
readShowDownloadsWhenStarting: function ()
|
||||
{
|
||||
this.showDownloadsWhenStartingPrefChanged();
|
||||
|
||||
// don't override the preference's value in UI
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables or disables the "close Downloads manager when downloads finished"
|
||||
* preference element, consequently updating the associated UI.
|
||||
*/
|
||||
showDownloadsWhenStartingPrefChanged: function ()
|
||||
{
|
||||
var showWhenStartingPref = document.getElementById("browser.download.manager.showWhenStarting");
|
||||
var closeWhenDonePref = document.getElementById("browser.download.manager.closeWhenDone");
|
||||
closeWhenDonePref.disabled = !showWhenStartingPref.value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables the folder field and Browse button based on whether a
|
||||
* default download directory is being used.
|
||||
|
|
|
@ -31,13 +31,6 @@
|
|||
onchange="gMainPane.updateBrowserStartupLastSession();"/>
|
||||
|
||||
<!-- Downloads -->
|
||||
<preference id="browser.download.manager.showWhenStarting"
|
||||
name="browser.download.manager.showWhenStarting"
|
||||
type="bool"
|
||||
onchange="gMainPane.showDownloadsWhenStartingPrefChanged();"/>
|
||||
<preference id="browser.download.manager.closeWhenDone"
|
||||
name="browser.download.manager.closeWhenDone"
|
||||
type="bool"/>
|
||||
<preference id="browser.download.useDownloadDir"
|
||||
name="browser.download.useDownloadDir"
|
||||
type="bool"/>
|
||||
|
@ -160,19 +153,6 @@
|
|||
<groupbox id="downloadsGroup" data-category="paneGeneral" hidden="true">
|
||||
<caption label="&downloads.label;"/>
|
||||
|
||||
<checkbox id="showWhenDownloading"
|
||||
label="&showWhenDownloading.label;"
|
||||
accesskey="&showWhenDownloading.accesskey;"
|
||||
preference="browser.download.manager.showWhenStarting"
|
||||
onsyncfrompreference="return gMainPane.readShowDownloadsWhenStarting();"/>
|
||||
<checkbox id="closeWhenDone"
|
||||
label="&closeWhenDone.label;"
|
||||
accesskey="&closeWhenDone.accesskey;"
|
||||
class="indent"
|
||||
preference="browser.download.manager.closeWhenDone"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<radiogroup id="saveWhere"
|
||||
preference="browser.download.useDownloadDir"
|
||||
onsyncfrompreference="return gMainPane.readUseDownloadDir();">
|
||||
|
|
|
@ -23,25 +23,12 @@ var gMainPane = {
|
|||
|
||||
this.updateBrowserStartupLastSession();
|
||||
|
||||
this.setupDownloadsWindowOptions();
|
||||
|
||||
// Notify observers that the UI is now ready
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService)
|
||||
.notifyObservers(window, "main-pane-loaded", null);
|
||||
},
|
||||
|
||||
setupDownloadsWindowOptions: function ()
|
||||
{
|
||||
let showWhenDownloading = document.getElementById("showWhenDownloading");
|
||||
let closeWhenDone = document.getElementById("closeWhenDone");
|
||||
|
||||
// These radio buttons should be hidden when the Downloads Panel is enabled.
|
||||
let shouldHide = !DownloadsCommon.useToolkitUI;
|
||||
showWhenDownloading.hidden = shouldHide;
|
||||
closeWhenDone.hidden = shouldHide;
|
||||
},
|
||||
|
||||
// HOME PAGE
|
||||
|
||||
/*
|
||||
|
@ -185,12 +172,6 @@ var gMainPane = {
|
|||
/*
|
||||
* Preferences:
|
||||
*
|
||||
* browser.download.showWhenStarting - bool
|
||||
* True if the Download Manager should be opened when a download is
|
||||
* started, false if it shouldn't be opened.
|
||||
* browser.download.closeWhenDone - bool
|
||||
* True if the Download Manager should be closed when all downloads
|
||||
* complete, false if it should be left open.
|
||||
* browser.download.useDownloadDir - bool
|
||||
* True - Save files directly to the folder configured via the
|
||||
* browser.download.folderList preference.
|
||||
|
@ -218,30 +199,6 @@ var gMainPane = {
|
|||
* deprecated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Updates preferences which depend upon the value of the preference which
|
||||
* determines whether the Downloads manager is opened at the start of a
|
||||
* download.
|
||||
*/
|
||||
readShowDownloadsWhenStarting: function ()
|
||||
{
|
||||
this.showDownloadsWhenStartingPrefChanged();
|
||||
|
||||
// don't override the preference's value in UI
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables or disables the "close Downloads manager when downloads finished"
|
||||
* preference element, consequently updating the associated UI.
|
||||
*/
|
||||
showDownloadsWhenStartingPrefChanged: function ()
|
||||
{
|
||||
var showWhenStartingPref = document.getElementById("browser.download.manager.showWhenStarting");
|
||||
var closeWhenDonePref = document.getElementById("browser.download.manager.closeWhenDone");
|
||||
closeWhenDonePref.disabled = !showWhenStartingPref.value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables the folder field and Browse button based on whether a
|
||||
* default download directory is being used.
|
||||
|
|
|
@ -50,13 +50,6 @@
|
|||
onchange="gMainPane.updateBrowserStartupLastSession();"/>
|
||||
|
||||
<!-- Downloads -->
|
||||
<preference id="browser.download.manager.showWhenStarting"
|
||||
name="browser.download.manager.showWhenStarting"
|
||||
type="bool"
|
||||
onchange="gMainPane.showDownloadsWhenStartingPrefChanged();"/>
|
||||
<preference id="browser.download.manager.closeWhenDone"
|
||||
name="browser.download.manager.closeWhenDone"
|
||||
type="bool"/>
|
||||
<preference id="browser.download.useDownloadDir"
|
||||
name="browser.download.useDownloadDir"
|
||||
type="bool"/>
|
||||
|
@ -117,16 +110,6 @@
|
|||
<groupbox id="downloadsGroup">
|
||||
<caption label="&downloads.label;"/>
|
||||
|
||||
<checkbox id="showWhenDownloading" label="&showWhenDownloading.label;"
|
||||
accesskey="&showWhenDownloading.accesskey;"
|
||||
preference="browser.download.manager.showWhenStarting"
|
||||
onsyncfrompreference="return gMainPane.readShowDownloadsWhenStarting();"/>
|
||||
<checkbox id="closeWhenDone" label="&closeWhenDone.label;"
|
||||
accesskey="&closeWhenDone.accesskey;" class="indent"
|
||||
preference="browser.download.manager.closeWhenDone"/>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<radiogroup id="saveWhere"
|
||||
preference="browser.download.useDownloadDir"
|
||||
onsyncfrompreference="return gMainPane.readUseDownloadDir();">
|
||||
|
|
|
@ -22,10 +22,6 @@
|
|||
|
||||
<!ENTITY downloads.label "Downloads">
|
||||
|
||||
<!ENTITY showWhenDownloading.label "Show the Downloads window when downloading a file">
|
||||
<!ENTITY showWhenDownloading.accesskey "D">
|
||||
<!ENTITY closeWhenDone.label "Close it when all downloads are finished">
|
||||
<!ENTITY closeWhenDone.accesskey "w">
|
||||
<!ENTITY saveTo.label "Save files to">
|
||||
<!ENTITY saveTo.accesskey "v">
|
||||
<!ENTITY chooseFolderWin.label "Browse…">
|
||||
|
|
Загрузка…
Ссылка в новой задаче