forked from mirrors/gecko-dev
Gives a site specific browser window a custom model ID and adds the same model ID to its shortcut. This makes the window appear distinct from the rest of Firefox's windows in the taskbar and allows for pinning the new entry to the taskbar. Differential Revision: https://phabricator.services.mozilla.com/D56780 --HG-- extra : moz-landing-system : lando
160 lines
4.1 KiB
JavaScript
160 lines
4.1 KiB
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/. */
|
|
|
|
var EXPORTED_SYMBOLS = ["WindowsSupport"];
|
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
const { XPCOMUtils } = ChromeUtils.import(
|
|
"resource://gre/modules/XPCOMUtils.jsm"
|
|
);
|
|
const { SiteSpecificBrowserService } = ChromeUtils.import(
|
|
"resource:///modules/SiteSpecificBrowserService.jsm"
|
|
);
|
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
OS: "resource://gre/modules/osfile.jsm",
|
|
ImageTools: "resource:///modules/ssb/ImageTools.jsm",
|
|
});
|
|
|
|
const shellService = Cc["@mozilla.org/browser/shell-service;1"].getService(
|
|
Ci.nsIWindowsShellService
|
|
);
|
|
|
|
const uiUtils = Cc["@mozilla.org/windows-ui-utils;1"].getService(
|
|
Ci.nsIWindowsUIUtils
|
|
);
|
|
|
|
const taskbar = Cc["@mozilla.org/windows-taskbar;1"].getService(
|
|
Ci.nsIWinTaskbar
|
|
);
|
|
|
|
const File = Components.Constructor(
|
|
"@mozilla.org/file/local;1",
|
|
Ci.nsIFile,
|
|
"initWithPath"
|
|
);
|
|
|
|
function buildGroupId(id) {
|
|
try {
|
|
return `${taskbar.defaultGroupId}.ssb.${id}`;
|
|
} catch (e) {
|
|
return `Firefox.ssb.${id}`;
|
|
}
|
|
}
|
|
|
|
const WindowsSupport = {
|
|
/**
|
|
* Installs an SSB by creating a shortcut to launch it on the user's desktop.
|
|
*
|
|
* @param {SiteSpecificBrowser} ssb the SSB to install.
|
|
*/
|
|
async install(ssb) {
|
|
if (!SiteSpecificBrowserService.useOSIntegration) {
|
|
return;
|
|
}
|
|
|
|
let dir = OS.Path.join(OS.Constants.Path.profileDir, "ssb", ssb.id);
|
|
await OS.File.makeDir(dir, {
|
|
from: OS.Constants.Path.profileDir,
|
|
ignoreExisting: true,
|
|
});
|
|
|
|
let iconFile = new File(OS.Path.join(dir, "icon.ico"));
|
|
|
|
// We should be embedding multiple icon sizes, but the current icon encoder
|
|
// does not support this. For now just embed a sensible size.
|
|
let icon = ssb.getIcon(128);
|
|
if (icon) {
|
|
let { container } = await ImageTools.loadImage(
|
|
Services.io.newURI(icon.src)
|
|
);
|
|
ImageTools.saveIcon(container, 128, 128, iconFile);
|
|
} else {
|
|
// TODO use a default icon file.
|
|
iconFile = null;
|
|
}
|
|
|
|
let desktop = Services.dirsvc.get("Desk", Ci.nsIFile);
|
|
let link = OS.Path.join(desktop.path, `${ssb.name}.lnk`);
|
|
|
|
shellService.createShortcut(
|
|
Services.dirsvc.get("XREExeF", Ci.nsIFile),
|
|
["-profile", OS.Constants.Path.profileDir, "-start-ssb", ssb.id],
|
|
ssb.name,
|
|
iconFile,
|
|
buildGroupId(ssb.id),
|
|
new File(link)
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Uninstalls an SSB by deleting its shortcut from the user's desktop.
|
|
*
|
|
* @param {SiteSpecificBrowser} ssb the SSB to uninstall.
|
|
*/
|
|
async uninstall(ssb) {
|
|
if (!SiteSpecificBrowserService.useOSIntegration) {
|
|
return;
|
|
}
|
|
|
|
let desktop = Services.dirsvc.get("Desk", Ci.nsIFile);
|
|
let link = OS.Path.join(desktop.path, `${ssb.name}.lnk`);
|
|
|
|
try {
|
|
await OS.File.remove(link);
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
|
|
let dir = OS.Path.join(OS.Constants.Path.profileDir, "ssb", ssb.id);
|
|
try {
|
|
await OS.File.removeDir(dir, {
|
|
ignoreAbsent: true,
|
|
ignorePermissions: true,
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Applies the necessary OS integration to an open SSB.
|
|
*
|
|
* Sets the window icon based on the available icons.
|
|
*
|
|
* @param {SiteSpecificBrowser} ssb the SSB.
|
|
* @param {DOMWindow} window the window showing the SSB.
|
|
*/
|
|
async applyOSIntegration(ssb, window) {
|
|
const getIcon = async size => {
|
|
let icon = ssb.getIcon(size);
|
|
if (!icon) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
let image = await ImageTools.loadImage(Services.io.newURI(icon.src));
|
|
return image.container;
|
|
} catch (e) {
|
|
console.error(e);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
if (!SiteSpecificBrowserService.useOSIntegration) {
|
|
return;
|
|
}
|
|
|
|
let icons = await Promise.all([
|
|
getIcon(uiUtils.systemSmallIconSize),
|
|
getIcon(uiUtils.systemLargeIconSize),
|
|
]);
|
|
|
|
if (icons[0] || icons[1]) {
|
|
uiUtils.setWindowIcon(window, icons[0], icons[1]);
|
|
}
|
|
|
|
taskbar.setGroupIdForWindow(window, buildGroupId(ssb.id));
|
|
},
|
|
};
|