Bug 1798212 - Convert downloads code to ES modules. r=mak

Differential Revision: https://phabricator.services.mozilla.com/D161012
This commit is contained in:
Mark Banner 2022-11-07 17:56:09 +00:00
parent 4c4f24bd35
commit a9d47c7a8c
23 changed files with 79 additions and 188 deletions

View file

@ -6,17 +6,11 @@
* Provides functions to prevent multiple automatic downloads.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadSpamProtection"];
const { Download, DownloadError } = ChromeUtils.import(
"resource://gre/modules/DownloadCore.jsm"
);
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -66,7 +60,7 @@ class WindowSpamProtection {
* A per-window DownloadList for blocked spam downloads. Registered views will
* be sent notifications about downloads in this list, so that blocked spam
* downloads can be represented in the UI. If spam downloads haven't been
* blocked in the window, this will be undefined. See DownloadList.jsm.
* blocked in the window, this will be undefined. See DownloadList.sys.mjs.
* @type {DownloadList | undefined}
*/
get spamList() {
@ -82,7 +76,7 @@ class WindowSpamProtection {
/**
* A per-window downloads indicator whose state depends on notifications from
* DownloadLists registered in the window (for example, the visual state of
* the downloads toolbar button). See DownloadsCommon.jsm for more details.
* the downloads toolbar button). See DownloadsCommon.sys.mjs for more details.
* @type {DownloadsIndicatorData}
*/
get indicator() {
@ -198,9 +192,9 @@ class WindowSpamProtection {
/**
* Responsible for detecting events related to downloads spam and notifying the
* relevant window's WindowSpamProtection object. This is a singleton object,
* constructed by DownloadIntegration.jsm when the first download is blocked.
* constructed by DownloadIntegration.sys.mjs when the first download is blocked.
*/
class DownloadSpamProtection {
export class DownloadSpamProtection {
/**
* Stores spam protection data per-window.
* @type {WeakMap<Window, WindowSpamProtection>}

View file

@ -4,10 +4,6 @@
* 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/. */
"use strict";
var EXPORTED_SYMBOLS = ["DownloadsCommon"];
/**
* Handles the Downloads panel shared methods and data access.
*
@ -30,9 +26,7 @@ var EXPORTED_SYMBOLS = ["DownloadsCommon"];
// Globals
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -144,7 +138,7 @@ PrefObserver.register({
* This object is exposed directly to the consumers of this JavaScript module,
* and provides shared methods for all the instances of the user interface.
*/
var DownloadsCommon = {
export var DownloadsCommon = {
// The following legacy constants are still returned by stateOfDownload, but
// individual properties of the Download object should normally be used.
DOWNLOAD_NOTSTARTED: -1,
@ -1208,7 +1202,7 @@ const DownloadsViewPrototype = {
* Called every time any state property of a Download may have changed,
* including progress properties.
*
* Note that progress notification changes are throttled at the Downloads.jsm
* Note that progress notification changes are throttled at the Downloads.sys.mjs
* API level, and there is no throttling mechanism in the front-end.
*
* @note Subclasses should override this and still call the base method.

View file

@ -8,13 +8,7 @@
* Handles the download progress indicator of the macOS Finder.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadsMacFinderProgress"];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -22,7 +16,7 @@ XPCOMUtils.defineLazyModuleGetters(lazy, {
Downloads: "resource://gre/modules/Downloads.jsm",
});
var DownloadsMacFinderProgress = {
export var DownloadsMacFinderProgress = {
/**
* Maps the path of the download, to the according progress indicator instance.
*/

View file

@ -8,15 +8,10 @@
* Handles the download progress indicator in the taskbar.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadsTaskbar"];
// Globals
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
XPCOMUtils.defineLazyModuleGetters(lazy, {
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
@ -54,7 +49,7 @@ XPCOMUtils.defineLazyGetter(lazy, "gGtkTaskbarProgress", function() {
/**
* Handles the download progress indicator in the taskbar.
*/
var DownloadsTaskbar = {
export var DownloadsTaskbar = {
/**
* Underlying DownloadSummary providing the aggregate download information, or
* null if the indicator has never been initialized.

View file

@ -7,13 +7,7 @@
* provides prototypes for objects that handle input and display information.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadsViewUI"];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -43,9 +37,7 @@ XPCOMUtils.defineLazyServiceGetter(
Ci.nsIApplicationReputationService
);
const { Integration } = ChromeUtils.importESModule(
"resource://gre/modules/Integration.sys.mjs"
);
import { Integration } from "resource://gre/modules/Integration.sys.mjs";
Integration.downloads.defineModuleGetter(
lazy,
@ -112,7 +104,7 @@ var gDownloadElementButtons = {
*/
var gDownloadListItemFragments = new WeakMap();
var DownloadsViewUI = {
export var DownloadsViewUI = {
/**
* Returns true if the given string is the name of a command that can be
* handled by the Downloads user interface, including standard commands.
@ -313,7 +305,7 @@ var DownloadsViewUI = {
);
/**
* In HelperAppDlg.jsm, we determine whether or not an "always open..." checkbox
* In HelperAppDlg.sys.mjs, we determine whether or not an "always open..." checkbox
* should appear in the unknownContentType window. Here, we use similar checks to
* determine if we should show the "always open similar files" context menu item.
*
@ -399,7 +391,7 @@ DownloadsViewUI.BaseView = class {
*
* The information to display is obtained through the associated Download object
* from the JavaScript API for downloads, and commands are executed using a
* combination of Download methods and DownloadsCommon.jsm helper functions.
* combination of Download methods and DownloadsCommon.sys.mjs helper functions.
*
* Specialized versions of this shell must be defined, and they are required to
* implement the "download" property or getter. Currently these objects are the

View file

@ -8,19 +8,7 @@
* inconsistency.
*/
"use strict";
var EXPORTED_SYMBOLS = [
"DownloadsViewableInternally",
"PREF_ENABLED_TYPES",
"PREF_BRANCH_WAS_REGISTERED",
"PREF_BRANCH_PREVIOUS_ACTION",
"PREF_BRANCH_PREVIOUS_ASK",
];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -42,14 +30,16 @@ ChromeUtils.defineESModuleGetters(lazy, {
});
const PREF_BRANCH = "browser.download.viewableInternally.";
const PREF_ENABLED_TYPES = PREF_BRANCH + "enabledTypes";
const PREF_BRANCH_WAS_REGISTERED = PREF_BRANCH + "typeWasRegistered.";
const PREF_BRANCH_PREVIOUS_ACTION =
export const PREF_ENABLED_TYPES = PREF_BRANCH + "enabledTypes";
export const PREF_BRANCH_WAS_REGISTERED = PREF_BRANCH + "typeWasRegistered.";
export const PREF_BRANCH_PREVIOUS_ACTION =
PREF_BRANCH + "previousHandler.preferredAction.";
const PREF_BRANCH_PREVIOUS_ASK =
export const PREF_BRANCH_PREVIOUS_ASK =
PREF_BRANCH + "previousHandler.alwaysAskBeforeHandling.";
let DownloadsViewableInternally = {
export let DownloadsViewableInternally = {
/**
* Initially add/remove handlers, watch pref, register with Integration.downloads.
*/

View file

@ -12,17 +12,17 @@ BROWSER_CHROME_MANIFESTS += ["test/browser/browser.ini"]
JAR_MANIFESTS += ["jar.mn"]
EXTRA_JS_MODULES += [
"DownloadsCommon.jsm",
"DownloadSpamProtection.jsm",
"DownloadsTaskbar.jsm",
"DownloadsViewableInternally.jsm",
"DownloadsViewUI.jsm",
"DownloadsCommon.sys.mjs",
"DownloadSpamProtection.sys.mjs",
"DownloadsTaskbar.sys.mjs",
"DownloadsViewableInternally.sys.mjs",
"DownloadsViewUI.sys.mjs",
]
toolkit = CONFIG["MOZ_WIDGET_TOOLKIT"]
if toolkit == "cocoa":
EXTRA_JS_MODULES += ["DownloadsMacFinderProgress.jsm"]
EXTRA_JS_MODULES += ["DownloadsMacFinderProgress.sys.mjs"]
with Files("**"):
BUG_COMPONENT = ("Firefox", "Downloads Panel")

View file

@ -318,7 +318,7 @@ class BackgroundFileSaverOutputStream : public BackgroundFileSaver,
////////////////////////////////////////////////////////////////////////////////
//// BackgroundFileSaverStreamListener. This class is instantiated by
// nsExternalHelperAppService, DownloadCore.jsm, and possibly others.
// nsExternalHelperAppService, DownloadCore.sys.mjs, and possibly others.
class BackgroundFileSaverStreamListener final : public BackgroundFileSaver,
public nsIStreamListener {

View file

@ -130,7 +130,7 @@ const NS_ERROR_MODULE_NETWORK = 6;
// A reimplementation of NS_ERROR_GET_MODULE, which surprisingly doesn't seem
// to exist anywhere in .js code in a way that can be reused.
// This is taken from DownloadCore.jsm.
// This is taken from DownloadCore.sys.mjs.
function NS_ERROR_GET_MODULE(code) {
return ((code & 0x7fff0000) >> 16) - NS_ERROR_MODULE_BASE_OFFSET;
}

View file

@ -4,30 +4,12 @@
/**
* Main implementation of the Downloads API objects. Consumers should get
* references to these objects through the "Downloads.jsm" module.
* references to these objects through the "Downloads.sys.mjs" module.
*/
"use strict";
var EXPORTED_SYMBOLS = [
"Download",
"DownloadSource",
"DownloadTarget",
"DownloadError",
"DownloadSaver",
"DownloadCopySaver",
"DownloadLegacySaver",
];
const { Integration } = ChromeUtils.importESModule(
"resource://gre/modules/Integration.sys.mjs"
);
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
const { AppConstants } = ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
import { Integration } from "resource://gre/modules/Integration.sys.mjs";
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
@ -137,7 +119,7 @@ const kProgressUpdateIntervalMs = 400;
* is transient, though it can be included in a DownloadList so that it can be
* managed by the user interface and persisted across sessions.
*/
var Download = function() {
export var Download = function() {
this._deferSucceeded = lazy.PromiseUtils.defer();
};
@ -1350,7 +1332,7 @@ const kPlainSerializableDownloadProperties = [
/**
* Creates a new Download object from a serializable representation. This
* function is used by the createDownload method of Downloads.jsm when a new
* function is used by the createDownload method of Downloads.sys.mjs when a new
* Download object is requested, thus some properties may refer to live objects
* in place of their serializable representations.
*
@ -1430,7 +1412,7 @@ Download.fromSerializable = function(aSerializable) {
/**
* Represents the source of a download, for example a document or an URI.
*/
var DownloadSource = function() {};
export var DownloadSource = function() {};
DownloadSource.prototype = {
/**
@ -1671,7 +1653,7 @@ DownloadSource.fromSerializable = function(aSerializable) {
* Represents the target of a download, for example a file in the global
* downloads directory, or a file in the system temporary directory.
*/
var DownloadTarget = function() {};
export var DownloadTarget = function() {};
DownloadTarget.prototype = {
/**
@ -1834,7 +1816,7 @@ DownloadTarget.fromSerializable = function(aSerializable) {
* The properties object may also contain any of the DownloadError's
* because properties, which will be set accordingly in the error object.
*/
var DownloadError = function(aProperties) {
export var DownloadError = function(aProperties) {
const NS_ERROR_MODULE_BASE_OFFSET = 0x45;
const NS_ERROR_MODULE_NETWORK = 6;
const NS_ERROR_MODULE_FILES = 13;
@ -2002,7 +1984,7 @@ DownloadError.fromSerializable = function(aSerializable) {
/**
* Template for an object that actually transfers the data for the download.
*/
var DownloadSaver = function() {};
export var DownloadSaver = function() {};
DownloadSaver.prototype = {
/**
@ -2127,7 +2109,7 @@ DownloadSaver.fromSerializable = function(aSerializable) {
/**
* Saver object that simply copies the entire source file to the target.
*/
var DownloadCopySaver = function() {};
export var DownloadCopySaver = function() {};
DownloadCopySaver.prototype = {
__proto__: DownloadSaver.prototype,
@ -2730,7 +2712,7 @@ DownloadCopySaver.fromSerializable = function(aSerializable) {
*
* For more background on the process, see the DownloadLegacyTransfer object.
*/
var DownloadLegacySaver = function() {
export var DownloadLegacySaver = function() {
this.deferExecuted = lazy.PromiseUtils.defer();
this.deferCanceled = lazy.PromiseUtils.defer();
};

View file

@ -11,16 +11,10 @@
* exposed to allow the consumers to integrate with history view commands.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadHistory"];
const { DownloadList } = ChromeUtils.import(
"resource://gre/modules/DownloadList.jsm"
);
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -55,7 +49,7 @@ const METADATA_STATE_DIRTY = 8;
* Provides methods to retrieve downloads from previous sessions and store
* downloads for future sessions.
*/
var DownloadHistory = {
export var DownloadHistory = {
/**
* Retrieves the main DownloadHistoryList object which provides a unified view
* on downloads from both previous browsing sessions and this session.

View file

@ -7,22 +7,13 @@
* example the global prompts on shutdown.
*/
"use strict";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
var EXPORTED_SYMBOLS = ["DownloadIntegration"];
const { AppConstants } = ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
const { Downloads } = ChromeUtils.import(
"resource://gre/modules/Downloads.jsm"
);
const { Integration } = ChromeUtils.importESModule(
"resource://gre/modules/Integration.sys.mjs"
);
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { Integration } from "resource://gre/modules/Integration.sys.mjs";
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -159,7 +150,7 @@ const kVerdictMap = {
* Provides functions to integrate with the host application, handling for
* example the global prompts on shutdown.
*/
var DownloadIntegration = {
export var DownloadIntegration = {
/**
* Main DownloadStore object for loading and saving the list of persistent
* downloads, or null if the download list was never requested and thus it

View file

@ -6,14 +6,12 @@
* This component implements the XPCOM interfaces required for integration with
* the legacy download components.
*
* New code is expected to use the "Downloads.jsm" module directly, without
* New code is expected to use the "Downloads.sys.mjs" module directly, without
* going through the interfaces implemented in this XPCOM component. These
* interfaces are only maintained for backwards compatibility with components
* that still work synchronously on the main thread.
*/
"use strict";
const lazy = {};
ChromeUtils.defineModuleGetter(
@ -55,7 +53,7 @@ ChromeUtils.defineModuleGetter(
* expectations, for example by ensuring the target file exists when the
* download is successful, even if the source has a size of zero bytes.
*/
function DownloadLegacyTransfer() {
export function DownloadLegacyTransfer() {
this._promiseDownload = new Promise(r => (this._resolveDownload = r));
}
@ -509,5 +507,3 @@ DownloadLegacyTransfer.prototype = {
*/
_signatureInfo: null,
};
var EXPORTED_SYMBOLS = ["DownloadLegacyTransfer"];

View file

@ -6,14 +6,6 @@
* Provides collections of Download objects and aggregate views on them.
*/
"use strict";
var EXPORTED_SYMBOLS = [
"DownloadList",
"DownloadCombinedList",
"DownloadSummary",
];
const kFileExtensions = [
"aac",
"adt",
@ -146,7 +138,7 @@ const TELEMETRY_EVENT_CATEGORY = "downloads";
* Represents a collection of Download objects that can be viewed and managed by
* the user interface, and persisted across sessions.
*/
var DownloadList = function() {
export var DownloadList = function() {
this._downloads = [];
this._views = new Set();
};
@ -384,7 +376,7 @@ DownloadList.prototype = {
* @param aPrivateList
* Underlying DownloadList containing private downloads.
*/
var DownloadCombinedList = function(aPublicList, aPrivateList) {
export var DownloadCombinedList = function(aPublicList, aPrivateList) {
DownloadList.call(this);
this._publicList = aPublicList;
this._privateList = aPrivateList;
@ -495,7 +487,7 @@ DownloadCombinedList.prototype = {
/**
* Provides an aggregated view on the contents of a DownloadList.
*/
var DownloadSummary = function() {
export var DownloadSummary = function() {
this._downloads = [];
this._views = new Set();
};

View file

@ -6,11 +6,7 @@
* Provides methods for giving names and paths to files being downloaded.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadPaths"];
var DownloadPaths = {
export var DownloadPaths = {
/**
* Sanitizes an arbitrary string via mimeSvc.validateFileNameForSaving.
*

View file

@ -26,17 +26,11 @@
* }
*/
"use strict";
// Time after which insecure downloads that have not been dealt with on shutdown
// get removed (5 minutes).
const MAX_INSECURE_DOWNLOAD_AGE_MS = 5 * 60 * 1000;
var EXPORTED_SYMBOLS = ["DownloadStore"];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
const lazy = {};
@ -63,7 +57,7 @@ XPCOMUtils.defineLazyGetter(lazy, "gTextEncoder", function() {
* @param aPath
* String containing the file path where data should be saved.
*/
var DownloadStore = function(aList, aPath) {
export var DownloadStore = function(aList, aPath) {
this.list = aList;
this.path = aPath;
};

View file

@ -6,16 +6,8 @@
* Provides functions to handle status and messages in the user interface.
*/
"use strict";
var EXPORTED_SYMBOLS = ["DownloadUIHelper"];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
const { AppConstants } = ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
@ -45,7 +37,7 @@ const kStringsRequiringFormatting = {
/**
* Provides functions to handle status and messages in the user interface.
*/
var DownloadUIHelper = {
export var DownloadUIHelper = {
/**
* Returns an object that can be used to display prompts related to downloads.
*

View file

@ -6,13 +6,8 @@
* Main entry point to get references to all the back-end objects.
*/
"use strict";
import { Integration } from "resource://gre/modules/Integration.sys.mjs";
var EXPORTED_SYMBOLS = ["Downloads"];
const { Integration } = ChromeUtils.importESModule(
"resource://gre/modules/Integration.sys.mjs"
);
const { Download, DownloadError } = ChromeUtils.import(
"resource://gre/modules/DownloadCore.jsm"
);
@ -45,7 +40,7 @@ Integration.downloads.defineModuleGetter(
* This object is exposed directly to the consumers of this JavaScript module,
* and provides the only entry point to get references to back-end objects.
*/
var Downloads = {
export var Downloads = {
/**
* Work on downloads that were not started from a private browsing window.
*/

View file

@ -8,7 +8,7 @@ Classes = [
{
'cid': '{1b4c85df-cbdd-4bb6-b04e-613caece083c}',
'contract_ids': ['@mozilla.org/transfer;1'],
'jsm': 'resource://gre/modules/DownloadLegacy.jsm',
'esModule': 'resource://gre/modules/DownloadLegacy.sys.mjs',
'constructor': 'DownloadLegacyTransfer',
},
]

View file

@ -30,14 +30,14 @@ if CONFIG["OS_ARCH"] == "WINNT":
]
EXTRA_JS_MODULES += [
"DownloadCore.jsm",
"DownloadIntegration.jsm",
"DownloadLegacy.jsm",
"DownloadList.jsm",
"DownloadPaths.jsm",
"Downloads.jsm",
"DownloadStore.jsm",
"DownloadUIHelper.jsm",
"DownloadCore.sys.mjs",
"DownloadIntegration.sys.mjs",
"DownloadLegacy.sys.mjs",
"DownloadList.sys.mjs",
"DownloadPaths.sys.mjs",
"Downloads.sys.mjs",
"DownloadStore.sys.mjs",
"DownloadUIHelper.sys.mjs",
]
XPCOM_MANIFESTS += [
@ -46,7 +46,7 @@ XPCOM_MANIFESTS += [
if CONFIG["MOZ_PLACES"]:
EXTRA_JS_MODULES += [
"DownloadHistory.jsm",
"DownloadHistory.sys.mjs",
]
FINAL_LIBRARY = "xul"

View file

@ -2,7 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests for the "DownloadPaths.jsm" JavaScript module.
* Tests for the "DownloadPaths.sys.mjs" JavaScript module.
*/
function testSanitize(leafName, expectedLeafName, options = {}) {

View file

@ -208,7 +208,7 @@ class DownloadItem {
return null;
} // TODO
get estimatedEndTime() {
// Based on the code in summarizeDownloads() in DownloadsCommon.jsm
// Based on the code in summarizeDownloads() in DownloadsCommon.sys.mjs
if (this.download.hasProgress && this.download.speed > 0) {
let sizeLeft = this.download.totalBytes - this.download.currentBytes;
let timeLeftInSeconds = sizeLeft / this.download.speed;
@ -317,7 +317,7 @@ class DownloadItem {
}
// DownloadMap maps back and forth between the numeric identifiers used in
// the downloads WebExtension API and a Download object from the Downloads jsm.
// the downloads WebExtension API and a Download object from the Downloads sys.mjs.
// TODO Bug 1247794: make id and extension info persistent
const DownloadMap = new (class extends EventEmitter {
constructor() {

View file

@ -191,7 +191,7 @@ static nsresult UnescapeFragment(const nsACString& aFragment, nsIURI* aURI,
* Obtains the directory to use. This tends to vary per platform, and
* needs to be consistent throughout our codepaths. For platforms where
* helper apps use the downloads directory, this should be kept in
* sync with DownloadIntegration.jsm.
* sync with DownloadIntegration.sys.mjs.
*
* Optionally skip availability of the directory and storage.
*/