/* 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/. */
"use strict";
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
);
XPCOMUtils.defineLazyServiceGetter(
this,
"ProfileService",
"@mozilla.org/toolkit/profile-service;1",
"nsIToolkitProfileService"
);
async
function flush() {
try {
await ProfileService.asyncFlush();
rebuildProfileList();
}
catch (e) {
let [title, msg, button] = await document.l10n.formatValues([
{ id:
"profiles-flush-fail-title" },
{
id:
e.result == Cr.NS_ERROR_DATABASE_CHANGED
?
"profiles-flush-conflict"
:
"profiles-flush-failed",
},
{ id:
"profiles-flush-restart-button" },
]);
const PS = Ci.nsIPromptService;
let result = Services.prompt.confirmEx(
window,
title,
msg,
PS.BUTTON_POS_0 * PS.BUTTON_TITLE_CANCEL +
PS.BUTTON_POS_1 * PS.BUTTON_TITLE_IS_STRING,
null,
button,
null,
null,
{}
);
if (result == 1) {
restart(
false);
}
}
}
function rebuildProfileList() {
let parent = document.getElementById(
"profiles");
while (parent.firstChild) {
parent.firstChild.remove();
}
let defaultProfile;
try {
defaultProfile = ProfileService.defaultProfile;
}
catch (e) {}
let currentProfile = ProfileService.currentProfile;
for (let profile of ProfileService.profiles) {
let isCurrentProfile = profile == currentProfile;
let isInUse = isCurrentProfile;
if (!isInUse) {
try {
let lock = profile.lock({});
lock.unlock();
}
catch (e) {
if (
e.result != Cr.NS_ERROR_FILE_NOT_DIRECTORY &&
e.result != Cr.NS_ERROR_FILE_NOT_FOUND
) {
isInUse =
true;
}
}
}
display({
profile,
isDefault: profile == defaultProfile,
isCurrentProfile,
isInUse,
});
}
}
function display(profileData) {
let parent = document.getElementById(
"profiles");
let div = document.createElement(
"div");
parent.appendChild(div);
let name = document.createElement(
"h2");
div.appendChild(name);
document.l10n.setAttributes(name,
"profiles-name", {
name: profileData.profile.name,
});
if (profileData.isCurrentProfile) {
let currentProfile = document.createElement(
"h3");
document.l10n.setAttributes(currentProfile,
"profiles-current-profile");
div.appendChild(currentProfile);
}
else if (profileData.isInUse) {
let currentProfile = document.createElement(
"h3");
document.l10n.setAttributes(currentProfile,
"profiles-in-use-profile");
div.appendChild(currentProfile);
}
let table = document.createElement(
"table");
div.appendChild(table);
let tbody = document.createElement(
"tbody");
table.appendChild(tbody);
function createItem(title, value, dir =
false) {
let tr = document.createElement(
"tr");
tbody.appendChild(tr);
let th = document.createElement(
"th");
th.setAttribute(
"class",
"column");
document.l10n.setAttributes(th, title);
tr.appendChild(th);
let td = document.createElement(
"td");
tr.appendChild(td);
if (dir) {
td.appendChild(document.createTextNode(value.path));
if (value.exists()) {
let button = document.createElement(
"button");
button.setAttribute(
"class",
"opendir");
document.l10n.setAttributes(button,
"profiles-opendir");
td.appendChild(button);
button.addEventListener(
"click",
function () {
value.reveal();
});
}
}
else {
document.l10n.setAttributes(td, value);
}
}
createItem(
"profiles-is-default",
profileData.isDefault ?
"profiles-yes" :
"profiles-no"
);
createItem(
"profiles-rootdir", profileData.profile.rootDir,
true);
if (profileData.profile.localDir.path != profileData.profile.rootDir.path) {
createItem(
"profiles-localdir", profileData.profile.localDir,
true);
}
let renameButton = document.createElement(
"button");
document.l10n.setAttributes(renameButton,
"profiles-rename");
renameButton.onclick =
function () {
renameProfile(profileData.profile);
};
div.appendChild(renameButton);
if (!profileData.isInUse) {
let removeButton = document.createElement(
"button");
document.l10n.setAttributes(removeButton,
"profiles-remove");
removeButton.onclick =
function () {
removeProfile(profileData.profile);
};
div.appendChild(removeButton);
}
if (!profileData.isDefault) {
let defaultButton = document.createElement(
"button");
document.l10n.setAttributes(defaultButton,
"profiles-set-as-default");
defaultButton.onclick =
function () {
defaultProfile(profileData.profile);
};
div.appendChild(defaultButton);
}
if (!profileData.isInUse) {
let runButton = document.createElement(
"button");
document.l10n.setAttributes(runButton,
"profiles-launch-profile");
runButton.onclick =
function () {
openProfile(profileData.profile);
};
div.appendChild(runButton);
}
let sep = document.createElement(
"hr");
div.appendChild(sep);
}
// This is called from the createProfileWizard.xhtml dialog.
function CreateProfile(profile) {
// The wizard created a profile, just make it the default.
defaultProfile(profile);
}
function createProfileWizard() {
// This should be rewritten in HTML eventually.
window.browsingContext.topChromeWindow.openDialog(
"chrome://mozapps/content/profile/createProfileWizard.xhtml",
"",
"centerscreen,chrome,modal,titlebar",
ProfileService,
{ CreateProfile }
);
}
async
function renameProfile(profile) {
let newName = { value: profile.name };
let [title, msg] = await document.l10n.formatValues([
{ id:
"profiles-rename-profile-title" },
{ id:
"profiles-rename-profile", args: { name: profile.name } },
]);
if (Services.prompt.prompt(window, title, msg, newName,
null, { value: 0 })) {
newName = newName.value;
if (newName == profile.name) {
return;
}
try {
profile.name = newName;
}
catch (e) {
let [title, msg] = await document.l10n.formatValues([
{ id:
"profiles-invalid-profile-name-title" },
{ id:
"profiles-invalid-profile-name", args: { name: newName } },
]);
Services.prompt.alert(window, title, msg);
return;
}
flush();
}
}
async
function removeProfile(profile) {
let deleteFiles =
false;
if (profile.rootDir.exists()) {
let [title, msg, dontDeleteStr, deleteStr] =
await document.l10n.formatValues([
{ id:
"profiles-delete-profile-title" },
{
id:
"profiles-delete-profile-confirm",
args: { dir: profile.rootDir.path },
},
{ id:
"profiles-dont-delete-files" },
{ id:
"profiles-delete-files" },
]);
let buttonPressed = Services.prompt.confirmEx(
window,
title,
msg,
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1 +
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_2,
dontDeleteStr,
null,
deleteStr,
null,
{ value: 0 }
);
if (buttonPressed == 1) {
return;
}
if (buttonPressed == 2) {
deleteFiles =
true;
}
}
// If we are deleting the default profile we must choose a different one.
let isDefault =
false;
try {
isDefault = ProfileService.defaultProfile == profile;
}
catch (e) {}
if (isDefault) {
for (let p of ProfileService.profiles) {
if (profile == p) {
continue;
}
if (isDefault) {
try {
ProfileService.defaultProfile = p;
}
catch (e) {
// This can happen on dev-edition if a non-default profile is in use.
// In such a case the next time that dev-edition is started it will
// find no default profile and just create a new one.
}
}
break;
}
}
try {
profile.removeInBackground(deleteFiles);
}
catch (e) {
let [title, msg] = await document.l10n.formatValues([
{ id:
"profiles-delete-profile-failed-title" },
{ id:
"profiles-delete-profile-failed-message" },
]);
Services.prompt.alert(window, title, msg);
return;
}
flush();
}
async
function defaultProfile(profile) {
try {
ProfileService.defaultProfile = profile;
flush();
}
catch (e) {
// This can happen on dev-edition.
let [title, msg] = await document.l10n.formatValues([
{ id:
"profiles-cannot-set-as-default-title" },
{ id:
"profiles-cannot-set-as-default-message" },
]);
Services.prompt.alert(window, title, msg);
}
}
function openProfile(profile) {
Services.startup.createInstanceWithProfile(profile);
}
function restart(safeMode) {
let cancelQuit = Cc[
"@mozilla.org/supports-PRBool;1"].createInstance(
Ci.nsISupportsPRBool
);
Services.obs.notifyObservers(
cancelQuit,
"quit-application-requested",
"restart"
);
if (cancelQuit.data) {
return;
}
let flags = Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart;
if (safeMode) {
Services.startup.restartInSafeMode(flags);
}
else {
Services.startup.quit(flags);
}
}
window.addEventListener(
"DOMContentLoaded",
function () {
let createButton = document.getElementById(
"create-button");
createButton.addEventListener(
"click", createProfileWizard);
let restartSafeModeButton = document.getElementById(
"restart-in-safe-mode-button"
);
if (!Services.policies || Services.policies.isAllowed(
"safeMode")) {
restartSafeModeButton.addEventListener(
"click", () => {
restart(
true);
});
}
else {
restartSafeModeButton.setAttribute(
"disabled",
"true");
}
let restartNormalModeButton = document.getElementById(
"restart-button");
restartNormalModeButton.addEventListener(
"click", () => {
restart(
false);
});
if (ProfileService.isListOutdated) {
document.getElementById(
"owned").hidden =
true;
}
else {
document.getElementById(
"conflict").hidden =
true;
rebuildProfileList();
}
},
{ once:
true }
);