Source code
Revision control
Copy as Markdown
Other Tools
/* 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
import { TaskbarTabsPinBase } from "moz-src:///browser/components/taskbartabs/TaskbarTabsPinBase.sys.mjs";
let lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
ShellService: "moz-src:///browser/components/shell/ShellService.sys.mjs",
});
/**
* Pins Taskbar Tabs on non-MSIX Windows by creating a shortcut in the Start
* Menu and pinning it to the taskbar.
*/
export class TaskbarTabsPinWin extends TaskbarTabsPinBase {
async createShortcut(aTaskbarTab, aIconFile, aArgs, _aWindow) {
this._logConsole.info("Creating Taskbar Tabs shortcut.");
let { relativePath, description } =
await this.#generateShortcutInfo(aTaskbarTab);
this._logConsole.debug(
`Using shortcut path relative to Programs folder: ${relativePath}`
);
await lazy.ShellService.createShortcut(
Services.dirsvc.get("XREExeF", Ci.nsIFile),
aArgs,
description,
aIconFile,
0,
aTaskbarTab.id, // AUMID
"Programs",
relativePath
);
return relativePath;
}
async pinShortcut(aTaskbarTab, aShortcut) {
let pinResult = await lazy.ShellService.pinShortcutToTaskbar(
aTaskbarTab.id,
"Programs",
aShortcut
);
return pinResult === Ci.nsIWindowsShellService.REJECTED;
}
unpinFromTaskbar(aRelativePath) {
lazy.ShellService.unpinShortcutFromTaskbar("Programs", aRelativePath);
}
async deleteShortcut(aRelativePath) {
await lazy.ShellService.deleteShortcut("Programs", aRelativePath);
}
/**
* Gets a Localization object to use when creating shortcuts.
*
* @returns {Localization} An object to access localized strings.
*/
static _getLocalization() {
return new Localization(["branding/brand.ftl", "browser/taskbartabs.ftl"]);
}
/**
* Gets the path to the shortcut relative to the Start Menu folder,
* as well as the description that should be attached to the shortcut.
*
* @param {TaskbarTab} aTaskbarTab - The Taskbar Tab to get the path of.
* @returns {Promise<{description: string, relativePath: string}>} The description
* and relative path of the shortcut.
*/
async #generateShortcutInfo(aTaskbarTab) {
const l10n = TaskbarTabsPinWin._getLocalization();
let basename = sanitizeFilename(aTaskbarTab.name + ".lnk");
let dirname = await l10n.formatValue("taskbar-tab-shortcut-folder");
dirname = sanitizeFilename(dirname, { allowDirectoryNames: true });
const description = await l10n.formatValue(
"taskbar-tab-shortcut-description",
{ name: aTaskbarTab.name }
);
return {
description,
relativePath: dirname + "\\" + basename,
};
}
}
/**
* Cleans up the filename so it can be saved safely. This means replacing invalid names
* (e.g. DOS devices) with others, or replacing invalid characters (e.g. asterisks on
* Windows) with underscores.
*
* @param {string} aWantedName - The name to validate and sanitize. Make sure
* that aWantedName has an extension if it will be saved with one.
* @param {object} aOptions - Options to affect the sanitization.
* @param {boolean} aOptions.allowDirectoryNames - Indicates that the name will be used
* as a directory. If so, the validation rules may be slightly more lax.
* @returns {string} The sanitized name.
*/
function sanitizeFilename(aWantedName, { allowDirectoryNames = false } = {}) {
const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let flags =
Ci.nsIMIMEService.VALIDATE_SANITIZE_ONLY |
Ci.nsIMIMEService.VALIDATE_DONT_COLLAPSE_WHITESPACE |
// Don't add .download to the name if it ends with .lnk.
Ci.nsIMIMEService.VALIDATE_ALLOW_INVALID_FILENAMES;
if (allowDirectoryNames) {
flags |= Ci.nsIMIMEService.VALIDATE_ALLOW_DIRECTORY_NAMES;
}
return mimeService.validateFileNameForSaving(aWantedName, "", flags);
}