зеркало из https://github.com/mozilla/gecko-dev.git
417 строки
11 KiB
JavaScript
417 строки
11 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/. */
|
|
|
|
"use strict";
|
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
const { XPCOMUtils } = ChromeUtils.import(
|
|
"resource://gre/modules/XPCOMUtils.jsm"
|
|
);
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(
|
|
this,
|
|
"ProfileService",
|
|
"@mozilla.org/toolkit/profile-service;1",
|
|
"nsIToolkitProfileService"
|
|
);
|
|
|
|
async function flush() {
|
|
try {
|
|
ProfileService.flush();
|
|
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_TARGET_DOES_NOT_EXIST &&
|
|
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(e) {
|
|
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.xul 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.docShell.rootTreeItem.domWindow.openDialog(
|
|
"chrome://mozapps/content/profile/createProfileWizard.xul",
|
|
"",
|
|
"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) {
|
|
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(
|
|
Ci.nsISupportsPRBool
|
|
);
|
|
Services.obs.notifyObservers(
|
|
cancelQuit,
|
|
"quit-application-requested",
|
|
"restart"
|
|
);
|
|
|
|
if (cancelQuit.data) {
|
|
return;
|
|
}
|
|
|
|
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 }
|
|
);
|