author | Ehsan Akhgari <ehsan@mozilla.com> |
Thu, 06 Dec 2012 14:01:35 -0500 | |
changeset 115167 | cf0da0cd77237e1385a8667902115a09f418cd8d |
parent 115166 | 31d5dca2a3b4fff391dd501ab897d4080007f623 |
child 115168 | ea20935fa19d682387c60516a377409e85db7115 |
child 115224 | 9c06414c186477da3c3882be3f04c1d7e6cf9637 |
push id | 23978 |
push user | eakhgari@mozilla.com |
push date | Thu, 06 Dec 2012 19:01:42 +0000 |
treeherder | mozilla-central@cf0da0cd7723 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 801232 |
milestone | 20.0a1 |
backs out | 31d5dca2a3b4fff391dd501ab897d4080007f623 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/downloads/content/downloads.js +++ b/browser/components/downloads/content/downloads.js @@ -39,18 +39,16 @@ //////////////////////////////////////////////////////////////////////////////// //// Globals 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 /** * Main entry point for the downloads panel interface. */ const DownloadsPanel = { @@ -104,17 +102,17 @@ const DownloadsPanel = { // panel, starting the service will make us load their data asynchronously. Services.downloads; // Now that data loading has eventually started, load the required XUL // elements and initialize our views. DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay, function DP_I_callback() { DownloadsViewController.initialize(); - DownloadsCommon.getData(window).addView(DownloadsView); + DownloadsCommon.data.addView(DownloadsView); DownloadsPanel._attachEventListeners(); aCallback(); }); }, /** * Closes the downloads panel and frees the internal resources related to the * downloads. The downloads panel can be reopened later, even after this @@ -127,17 +125,17 @@ const DownloadsPanel = { } window.removeEventListener("unload", this.onWindowUnload, false); // Ensure that the panel is closed before shutting down. this.hidePanel(); DownloadsViewController.terminate(); - DownloadsCommon.getData(window).removeView(DownloadsView); + DownloadsCommon.data.removeView(DownloadsView); this._unattachEventListeners(); this._state = this.kStateUninitialized; }, ////////////////////////////////////////////////////////////////////////////// //// Panel interface @@ -227,17 +225,17 @@ const DownloadsPanel = { // Ignore events raised by nested popups. if (aEvent.target != aEvent.currentTarget) { return; } this._state = this.kStateShown; // Since at most one popup is open at any given time, we can set globally. - DownloadsCommon.getIndicatorData(window).attentionSuppressed = true; + DownloadsCommon.indicatorData.attentionSuppressed = true; // Ensure that an item is selected when the panel is focused. if (DownloadsView.richListBox.itemCount > 0 && !DownloadsView.richListBox.selectedItem) { DownloadsView.richListBox.selectedIndex = 0; } this._focusPanel(); @@ -246,17 +244,17 @@ const DownloadsPanel = { onPopupHidden: function DP_onPopupHidden(aEvent) { // Ignore events raised by nested popups. if (aEvent.target != aEvent.currentTarget) { return; } // Since at most one popup is open at any given time, we can set globally. - DownloadsCommon.getIndicatorData(window).attentionSuppressed = false; + DownloadsCommon.indicatorData.attentionSuppressed = false; // Allow the anchor to be hidden. DownloadsButton.releaseAnchor(); // Allow the panel to be reopened. this._state = this.kStateHidden; }, @@ -1107,21 +1105,17 @@ const DownloadsViewController = { // ancestors of the focused element. return !!element; }, isCommandEnabled: function DVC_isCommandEnabled(aCommand) { // Handle commands that are not selection-specific. if (aCommand == "downloadsCmd_clearList") { - if (PrivateBrowsingUtils.isWindowPrivate(window)) { - return Services.downloads.canCleanUpPrivate; - } else { - return Services.downloads.canCleanUp; - } + return Services.downloads.canCleanUp; } // Other commands are selection-specific. let element = DownloadsView.richListBox.selectedItem; return element && new DownloadsViewItemController(element).isCommandEnabled(aCommand); }, @@ -1158,35 +1152,31 @@ const DownloadsViewController = { /** * This object contains one key for each command that operates regardless of * the currently selected item in the list. */ commands: { downloadsCmd_clearList: function DVC_downloadsCmd_clearList() { - if (PrivateBrowsingUtils.isWindowPrivate(window)) { - Services.downloads.cleanUpPrivate(); - } else { - Services.downloads.cleanUp(); - } + Services.downloads.cleanUp(); } } }; //////////////////////////////////////////////////////////////////////////////// //// DownloadsViewItemController /** * Handles all the user interaction events, in particular the "commands", * related to a single item in the downloads list widgets. */ function DownloadsViewItemController(aElement) { let downloadGuid = aElement.getAttribute("downloadGuid"); - this.dataItem = DownloadsCommon.getData(window).dataItems[downloadGuid]; + this.dataItem = DownloadsCommon.data.dataItems[downloadGuid]; } DownloadsViewItemController.prototype = { ////////////////////////////////////////////////////////////////////////////// //// Constants get kPrefBdmAlertOnExeOpen() "browser.download.manager.alertOnEXEOpen", get kPrefBdmScanWhenDone() "browser.download.manager.scanWhenDone", @@ -1462,20 +1452,20 @@ const DownloadsSummary = { * Set to true to activate the summary. */ set active(aActive) { if (aActive == this._active || !this._summaryNode) { return this._active; } if (aActive) { - DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit) + DownloadsCommon.getSummary(DownloadsView.kItemCountLimit) .addView(this); } else { - DownloadsCommon.getSummary(window, DownloadsView.kItemCountLimit) + DownloadsCommon.getSummary(DownloadsView.kItemCountLimit) .removeView(this); DownloadsFooter.showingSummary = false; } return this._active = aActive; }, /**
--- a/browser/components/downloads/content/indicator.js +++ b/browser/components/downloads/content/indicator.js @@ -281,31 +281,31 @@ const DownloadsIndicatorView = { ensureInitialized: function DIV_ensureInitialized() { if (this._initialized) { return; } this._initialized = true; window.addEventListener("unload", this.onWindowUnload, false); - DownloadsCommon.getIndicatorData(window).addView(this); + DownloadsCommon.indicatorData.addView(this); }, /** * Frees the internal resources related to the indicator. */ ensureTerminated: function DIV_ensureTerminated() { if (!this._initialized) { return; } this._initialized = false; window.removeEventListener("unload", this.onWindowUnload, false); - DownloadsCommon.getIndicatorData(window).removeView(this); + DownloadsCommon.indicatorData.removeView(this); // Reset the view properties, so that a neutral indicator is displayed if we // are visible only temporarily as an anchor. this.counter = ""; this.percentComplete = 0; this.paused = false; this.attention = false; }, @@ -322,17 +322,17 @@ const DownloadsIndicatorView = { } function DIV_EO_callback() { this._operational = true; // If the view is initialized, we need to update the elements now that // they are finally available in the document. if (this._initialized) { - DownloadsCommon.getIndicatorData(window).refreshView(this); + DownloadsCommon.indicatorData.refreshView(this); } aCallback(); } DownloadsOverlayLoader.ensureOverlayLoaded( DownloadsButton.kIndicatorOverlay, DIV_EO_callback.bind(this)); @@ -503,17 +503,17 @@ const DownloadsIndicatorView = { // This function is registered as an event listener, we can't use "this". DownloadsIndicatorView.ensureTerminated(); }, 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; + DownloadsCommon.indicatorData.attention = false; BrowserDownloadsUI(); } else { DownloadsPanel.showPanel(); } aEvent.stopPropagation(); },
--- a/browser/components/downloads/src/DownloadsCommon.jsm +++ b/browser/components/downloads/src/DownloadsCommon.jsm @@ -51,20 +51,16 @@ XPCOMUtils.defineLazyServiceGetter(this, "@mozilla.org/browser/browserglue;1", "nsIBrowserGlue"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); 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; const kDownloadsStringBundleUrl = "chrome://browser/locale/downloads/downloads.properties"; const kDownloadsStringsRequiringFormatting = { sizeWithUnits: true, @@ -172,105 +168,47 @@ this.DownloadsCommon = { { try { return Services.prefs.getBoolPref("browser.download.useToolkitUI"); } catch (ex) { } return false; }, /** - * Get access to one of the DownloadsData or PrivateDownloadsData objects, - * depending on the privacy status of the window in question. + * Returns a reference to the DownloadsData singleton. * - * @param aWindow - * The browser window which owns the download button. + * This does not need to be a lazy getter, since no initialization is required + * at present. */ - getData: function DC_getData(aWindow) { - if (PrivateBrowsingUtils.isWindowPrivate(aWindow)) { - return PrivateDownloadsData; - } else { - return DownloadsData; - } - }, - - /** - * 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. - */ - initializeAllDataLinks: function DC_initializeAllDataLinks(aDownloadManagerService) { - DownloadsData.initializeDataLink(aDownloadManagerService); - PrivateDownloadsData.initializeDataLink(aDownloadManagerService); - }, + get data() DownloadsData, /** - * 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. + * Returns a reference to the DownloadsData singleton. * - * @param aActiveOnly - * True to load only active downloads from the database. + * This does not need to be a lazy getter, since no initialization is required + * at present. */ - 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; - } - }, + get indicatorData() 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. */ - getSummary: function DC_getSummary(aWindow, aNumToExclude) + _summary: null, + getSummary: function DC_getSummary(aNumToExclude) { - 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); + if (this._summary) { + return this._summary; } + return this._summary = new DownloadsSummaryData(aNumToExclude); }, - _summary: null, - _privateSummary: null, /** * Given an iterable collection of DownloadDataItems, generates and returns * statistics about that collection. * * @param aDataItems An iterable collection of DownloadDataItems. * * @return Object whose properties are the generated statistics. Currently, @@ -411,82 +349,59 @@ XPCOMUtils.defineLazyGetter(DownloadsCom * data. For example, the deletion of one or more downloads is notified through * the nsIObserver interface, while any state or progress change is notified * through the nsIDownloadProgressListener interface. * * Note that using this object does not automatically start the Download Manager * 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. */ -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 = { +const DownloadsData = { /** * 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) { // Start receiving real-time events. - aDownloadManagerService.addPrivacyAwareListener(this); + aDownloadManagerService.addListener(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 }, /** * Stops receiving events for current downloads and cancels any pending read. */ terminateDataLink: function DD_terminateDataLink() { 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); }, ////////////////////////////////////////////////////////////////////////////// //// 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. * * @param aView * DownloadsView object to be added. This reference must be passed to * removeView before termination. */ addView: function DD_addView(aView) @@ -535,16 +450,31 @@ DownloadsDataCtor.prototype = { aView.onDataLoadCompleted(); } }, ////////////////////////////////////////////////////////////////////////////// //// 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. */ clear: function DD_clear() { this._terminateDataAccess(); this.dataItems = {}; }, @@ -656,19 +586,17 @@ DownloadsDataCtor.prototype = { if (this._loadState == this.kLoadNone) { // 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 = this._isPrivate ? - Services.downloads.activePrivateDownloads : - Services.downloads.activeDownloads; + 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( @@ -676,20 +604,17 @@ DownloadsDataCtor.prototype = { ); } } 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. - let dbConnection = this._isPrivate ? - Services.downloads.privateDBConnection : - Services.downloads.DBConnection; - let statement = dbConnection.createAsyncStatement( + let statement = Services.downloads.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 { @@ -784,17 +709,16 @@ DownloadsDataCtor.prototype = { if (aStatus == Components.results.NS_ERROR_NOT_AVAILABLE) { this._removeDataItem(dataItemBinding.downloadGuid); } }.bind(this)); } } break; -#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING case "download-manager-database-type-changed": let pbs = Cc["@mozilla.org/privatebrowsing;1"] .getService(Ci.nsIPrivateBrowsingService); if (pbs.privateBrowsingEnabled) { // Save a reference to the persistent store before terminating access. this._persistentDataItems = this.dataItems; this.clear(); } else { @@ -802,31 +726,24 @@ DownloadsDataCtor.prototype = { this.clear(); this.dataItems = this._persistentDataItems; this._persistentDataItems = null; } // Reinitialize the views with the current items. View data has been // already invalidated by the previous calls. this._views.forEach(this._updateView, this); break; -#endif } }, ////////////////////////////////////////////////////////////////////////////// //// nsIDownloadProgressListener 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. let isNew = aState == nsIDM.DOWNLOAD_NOTSTARTED || aState == nsIDM.DOWNLOAD_QUEUED; let dataItem = this._getOrAddDataItem(aDownload, isNew); if (!dataItem) { @@ -862,22 +779,16 @@ DownloadsDataCtor.prototype = { }, 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; @@ -917,41 +828,33 @@ DownloadsDataCtor.prototype = { */ _notifyNewDownload: function DD_notifyNewDownload() { if (DownloadsCommon.useToolkitUI) { return; } // Show the panel in the most recent browser window, if present. - let browserWin = RecentWindow.getMostRecentBrowserWindow({ private: this._isPrivate }); + let browserWin = gBrowserGlue.getMostRecentBrowserWindow(); if (!browserWin) { return; } if (this.panelHasShownBefore) { // For new downloads after the first one, don't show the panel // automatically, but provide a visible notification in the topmost // browser window, if the status indicator is already visible. browserWin.DownloadsIndicatorView.showEventNotification(); return; } this.panelHasShownBefore = true; browserWin.DownloadsPanel.showPanel(); } }; -XPCOMUtils.defineLazyGetter(this, "PrivateDownloadsData", function() { - return new DownloadsDataCtor(true); -}); - -XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() { - return new DownloadsDataCtor(false); -}); - //////////////////////////////////////////////////////////////////////////////// //// 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. @@ -1208,46 +1111,32 @@ DownloadsDataItem.prototype = { */ const DownloadsViewPrototype = { ////////////////////////////////////////////////////////////////////////////// //// Registration of views /** * Array of view objects that should be notified when the available status * data changes. - * - * SUBCLASSES MUST OVERRIDE THIS PROPERTY. */ - _views: null, - - /** - * Determines whether this view object is over the private or non-private - * downloads. - * - * SUBCLASSES MUST OVERRIDE THIS PROPERTY. - */ - _isPrivate: false, + _views: [], /** * Adds an object to be notified when the available status data changes. * The specified object is initialized with the currently available status. * * @param aView * View object to be added. This reference must be * passed to removeView before termination. */ addView: function DVP_addView(aView) { // Start receiving events when the first of our views is registered. if (this._views.length == 0) { - if (this._isPrivate) { - PrivateDownloadsData.addView(this); - } else { - DownloadsData.addView(this); - } + DownloadsCommon.data.addView(this); } this._views.push(aView); this.refreshView(aView); }, /** * Updates the properties of an object previously added using addView. @@ -1273,21 +1162,17 @@ const DownloadsViewPrototype = { { let index = this._views.indexOf(aView); if (index != -1) { this._views.splice(index, 1); } // Stop receiving events when the last of our views is unregistered. if (this._views.length == 0) { - if (this._isPrivate) { - PrivateDownloadsData.removeView(this); - } else { - DownloadsData.removeView(this); - } + DownloadsCommon.data.removeView(this); } }, ////////////////////////////////////////////////////////////////////////////// //// Callback functions from DownloadsData /** * Indicates whether we are still loading downloads data asynchronously. @@ -1401,20 +1286,17 @@ const DownloadsViewPrototype = { * notifications it receives into overall status data, that is then broadcast to * the registered download status indicators. * * Note that using this object does not automatically start the Download Manager * 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. */ -function DownloadsIndicatorDataCtor(aPrivate) { - this._isPrivate = aPrivate; -} -DownloadsIndicatorDataCtor.prototype = { +const DownloadsIndicatorData = { __proto__: DownloadsViewPrototype, /** * Removes an object previously added using addView. * * @param aView * DownloadsIndicatorView object to be removed. */ @@ -1486,35 +1368,33 @@ DownloadsIndicatorDataCtor.prototype = { * * @param aDataItem * DownloadsDataItem object for which the view item is requested. * * @return Object that can be used to notify item status events. */ 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) { - data.attention = true; + DownloadsIndicatorData.attention = true; } // Since the state of a download changed, reset the estimated time left. - data._lastRawTimeLeft = -1; - data._lastTimeLeft = -1; + DownloadsIndicatorData._lastRawTimeLeft = -1; + DownloadsIndicatorData._lastTimeLeft = -1; - data._updateViews(); + DownloadsIndicatorData._updateViews(); }, onProgressChange: function DIVI_onProgressChange() { - data._updateViews(); + DownloadsIndicatorData._updateViews(); } }); }, ////////////////////////////////////////////////////////////////////////////// //// Propagation of properties to our views // The following properties are updated by _refreshProperties and are then @@ -1604,19 +1484,17 @@ DownloadsIndicatorDataCtor.prototype = { /** * A generator function for the dataItems that this summary is currently * interested in. This generator is passed off to summarizeDownloads in order * to generate statistics about the dataItems we care about - in this case, * it's all dataItems for active downloads. */ _activeDataItems: function DID_activeDataItems() { - let dataItems = this._isPrivate ? PrivateDownloadsData.dataItems - : DownloadsData.dataItems; - for each (let dataItem in dataItems) { + for each (let dataItem in DownloadsCommon.data.dataItems) { if (dataItem && dataItem.inProgress) { yield dataItem; } } }, /** * Computes aggregate values based on the current state of downloads. @@ -1646,48 +1524,38 @@ DownloadsIndicatorDataCtor.prototype = { if (this._lastRawTimeLeft != summary.rawTimeLeft) { this._lastRawTimeLeft = summary.rawTimeLeft; this._lastTimeLeft = DownloadsCommon.smoothSeconds(summary.rawTimeLeft, this._lastTimeLeft); } 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 /** * DownloadsSummaryData is a view for DownloadsData that produces a summary * of all downloads after a certain exclusion point aNumToExclude. For example, * if there were 5 downloads in progress, and a DownloadsSummaryData was * 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(aIsPrivate, aNumToExclude) { +function DownloadsSummaryData(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 = []; // Floating point value indicating the last number of seconds estimated until // the longest download will finish. We need to store this value so that we // don't continuously apply smoothing if the actual download state has not // changed. This is set to -1 if the previous value is unknown. @@ -1701,19 +1569,16 @@ function DownloadsSummaryData(aIsPrivate // The following properties are updated by _refreshProperties and are then // propagated to the views. this._showingProgress = false; this._details = ""; this._description = ""; this._numActive = 0; this._percentComplete = -1; - - this._isPrivate = aIsPrivate; - this._views = []; } DownloadsSummaryData.prototype = { __proto__: DownloadsViewPrototype, /** * Removes an object previously added using addView. *
--- a/browser/components/downloads/src/DownloadsStartup.js +++ b/browser/components/downloads/src/DownloadsStartup.js @@ -26,32 +26,26 @@ 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"); -#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", ]; /** * CID of our implementation of nsIDownloadManagerUI. */ @@ -114,18 +108,18 @@ DownloadsStartup.prototype = { // 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)); + DownloadsCommon.data.initializeDataLink( + 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); @@ -140,59 +134,47 @@ DownloadsStartup.prototype = { if (!DownloadsCommon.useToolkitUI) { let removeFinishedDownloads = Services.prefs.getBoolPref( "browser.download.panel.removeFinishedDownloads"); aSubject.QueryInterface(Ci.nsISupportsPRInt32) .data = removeFinishedDownloads ? 0 : 2; } 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 // 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; -#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 // 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(); + DownloadsCommon.data.terminateDataLink(); // 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; @@ -271,27 +253,24 @@ DownloadsStartup.prototype = { return aValue; }, /** * Ensures that persistent download data is reloaded at the appropriate time. */ _ensureDataLoaded: function DS_ensureDataLoaded() { - if (!this._downloadsServiceInitialized -#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING - || gPrivateBrowsingService.privateBrowsingEnabled -#endif - ) { + if (!this._downloadsServiceInitialized || + gPrivateBrowsingService.privateBrowsingEnabled) { 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); + DownloadsCommon.data.ensurePersistentDataLoaded(!this._recoverAllDownloads); } }; //////////////////////////////////////////////////////////////////////////////// //// Module this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsStartup]);
--- a/browser/components/downloads/src/Makefile.in +++ b/browser/components/downloads/src/Makefile.in @@ -6,20 +6,17 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk EXTRA_COMPONENTS = \ BrowserDownloads.manifest \ + DownloadsStartup.js \ DownloadsUI.js \ $(NULL) -EXTRA_PP_COMPONENTS = \ - DownloadsStartup.js \ - $(NULL) - -EXTRA_PP_JS_MODULES = \ +EXTRA_JS_MODULES = \ DownloadsCommon.jsm \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/browser/components/downloads/test/browser/browser_basic_functionality.js +++ b/browser/components/downloads/test/browser/browser_basic_functionality.js @@ -28,23 +28,23 @@ function gen_test() var originalCountLimit = DownloadsView.kItemCountLimit; DownloadsView.kItemCountLimit = DownloadData.length; registerCleanupFunction(function () { DownloadsView.kItemCountLimit = originalCountLimit; }); try { // Ensure that state is reset in case previous tests didn't finish. - for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield; + for (let yy in gen_resetState()) 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(DownloadsCommon.getData(window))) yield; + for (let yy in gen_openPanel()) yield; // Test item data and count. This also tests the ordering of the display. let richlistbox = document.getElementById("downloadsListBox"); /* disabled for failing intermittently (bug 767828) is(richlistbox.children.length, DownloadData.length, "There is the correct number of richlistitems"); */ for (let i = 0; i < richlistbox.children.length; i++) { @@ -52,11 +52,11 @@ function gen_test() let dataItem = new DownloadsViewItemController(element).dataItem; is(dataItem.target, DownloadData[i].name, "Download names match up"); is(dataItem.state, DownloadData[i].state, "Download states match up"); is(dataItem.file, DownloadData[i].target, "Download targets match up"); is(dataItem.uri, DownloadData[i].source, "Download sources match up"); } } finally { // Clean up when the test finishes. - for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield; + for (let yy in gen_resetState()) yield; } }
--- a/browser/components/downloads/test/browser/browser_first_download_panel.js +++ b/browser/components/downloads/test/browser/browser_first_download_panel.js @@ -7,42 +7,42 @@ * Make sure the downloads panel only opens automatically on the first * download it notices. All subsequent downloads, even across sessions, should * not open the panel automatically. */ function gen_test() { try { // Ensure that state is reset in case previous tests didn't finish. - for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield; + for (let yy in gen_resetState()) yield; // With this set to false, we should automatically open the panel // the first time a download is started. - DownloadsCommon.getData(window).panelHasShownBefore = false; + DownloadsCommon.data.panelHasShownBefore = false; prepareForPanelOpen(); - DownloadsCommon.getData(window)._notifyNewDownload(); + DownloadsCommon.data._notifyNewDownload(); yield; // If we got here, that means the panel opened. DownloadsPanel.hidePanel(); - ok(DownloadsCommon.getData(window).panelHasShownBefore, + ok(DownloadsCommon.data.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.getData(window)._notifyNewDownload(); + DownloadsCommon.data._notifyNewDownload(); yield waitFor(2); } catch(e) { ok(false, e); } finally { // Clean up when the test finishes. - for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield; + for (let yy in gen_resetState()) yield; } } /** * Call this to record a test failure for the next time the downloads panel * opens. */ function panelShouldNotOpen()
--- a/browser/components/downloads/test/browser/head.js +++ b/browser/components/downloads/test/browser/head.js @@ -125,17 +125,17 @@ var testRunner = { // // The following functions are all generators that can be used inside the main // test generator to perform specific tasks asynchronously. To invoke these // subroutines correctly, an iteration syntax should be used: // // for (let yy in gen_example("Parameter")) yield; // -function gen_resetState(aData) +function gen_resetState() { let statement = Services.downloads.DBConnection.createAsyncStatement( "DELETE FROM moz_downloads"); try { statement.executeAsync({ handleResult: function(aResultSet) { }, handleError: function(aError) { @@ -150,18 +150,18 @@ function gen_resetState(aData) } finally { statement.finalize(); } // Reset any prefs that might have been changed. Services.prefs.clearUserPref("browser.download.panel.shown"); // Ensure that the panel is closed and data is unloaded. - aData.clear(); - aData._loadState = aData.kLoadNone; + DownloadsCommon.data.clear(); + DownloadsCommon.data._loadState = DownloadsCommon.data.kLoadNone; DownloadsPanel.hidePanel(); // Wait for focus on the main window. waitForFocus(testRunner.continueTest); yield; } function gen_addDownloadRows(aDataRows) @@ -219,17 +219,17 @@ function gen_openPanel(aData) let originalOnViewLoadCompleted = DownloadsPanel.onViewLoadCompleted; DownloadsPanel.onViewLoadCompleted = function () { DownloadsPanel.onViewLoadCompleted = originalOnViewLoadCompleted; originalOnViewLoadCompleted.apply(this); testRunner.continueTest(); }; // Start loading all the downloads from the database asynchronously. - aData.ensurePersistentDataLoaded(false); + DownloadsCommon.data.ensurePersistentDataLoaded(false); // Wait for focus on the main window. waitForFocus(testRunner.continueTest); yield; // Open the downloads panel, waiting until loading is completed. DownloadsPanel.showPanel(); yield;